9

I'm trying to replicate the Java enums in Go. I would like to define an enum and then iterate over it to do some validations. Something like this in java

public enum Direction {
   NORTH,
   NORTHEAST,
   EAST,
   SOUTHEAST,
   SOUTH,
   SOUTHWEST,
   WEST,
   NORTHWEST
}

And the I would like to iterate over it, like this:

for (Direction dir : Direction.values()) {
  // do what you want
}

Is there a similar way to achieve this in Golang, I'm thinking in using structs but I don't think it's the best way.

Any ideas?

icza
  • 389,944
  • 63
  • 907
  • 827
rasilvap
  • 1,771
  • 3
  • 31
  • 70

2 Answers2

13

Go doesn't have an equivalent to Java's Enums, but usually iota comes handy when you want to create "enum-like" constants.

Your example may be described like this:

type Dir int

const (
    NORTH Dir = iota
    NORTHEAST
    EAST
    SOUTHEAST
    SOUTH
    SOUTHWEST
    WEST
    NORTHWEST
    dirLimit // this will be the last Dir + 1
)

And then to iterate over all directions (try it on the Go Playground):

for dir := Dir(0); dir < dirLimit; dir++ {
    // do what you want
}

Also see: Go Wiki: Iota

For advanced use and tricks with iota, see these answers:

How to skip a lot of values when define const variable with iota?

Enumerating string constants with iota

icza
  • 389,944
  • 63
  • 907
  • 827
1

The proper answer is already presented. I just want to add that if for some reason you don't want to see dirLimit in enum values, it can be replaced by such helper method:

type Dir int

const (
    NORTH Dir = iota
    NORTHEAST
    EAST
    SOUTHEAST
    SOUTH
    SOUTHWEST
    WEST
    NORTHWEST
)

func (d Dir) Ok() bool {
    switch d {
    case NORTH,
        NORTHEAST,
        EAST,
        SOUTHEAST,
        SOUTH,
        SOUTHWEST,
        WEST,
        NORTHWEST:
        return true
    }
    return false
}

Ok() returns true if the value is presented in enum. It allows to iterate over enum in the following way:

for dir := Dir(0); dir.Ok(); dir++ {
    fmt.Println(dir)
}

Here is a link to a full example in Go Playground.

I also recommend adding exhaustive linter to your project. It will check if all constants are presented in switch statements. In this way, the build fails if someone introduces a new enum value and forgets to add it into Ok() method. Mentioned linter can be used with golangci-lint tool.

Artem
  • 371
  • 4
  • 11