Golang Enum Tutorial [With Examples]


Written By - Antony Shikubu
Advertisement

Introduction to golang enum

Enum(enumerators) is a set of named constant values that allows developers to create constant values that have useful names. In other words , an enum groups related constants together into in type. In this article we will dive into what enums in Go and ways of defining an enum and its use cases.

Examples of enums.

  1. Months : January, February, March, April …
  2. Days of a week : Monday, Tuesday ….
  3. Campus Direction: North, South , East, West

Many programming languages have the concept of enumerations, where you can specify that a type can only have a limited set of values. Go doesn’t have an enumeration type. Instead, it has iota, which lets you assign an increasing value to a set of constants.

Given the above examples, it's now clear that enums are sets of constants that are known and limited. Enums are needed because :

  1. They prevent developers from using invalid values.
  2. They are used in grouping constants  that have related values
  3. They are used to define constants that share common behavior
  4. They increase code readability and maintainability

 

Defining constants

Let us define a set of related constant variables in Go. In this example , we are defining days of the week because they are a fixed set of 7 values. That is Monday, Tuesday , Wednesday , Thursday , Friday , Saturday and Sunday.

Example

package main
 
import "fmt"
 
const (
   Monday        = 0
   Tuesday       = 1
   Wednesday     = 2
   Thursday      = 3
   Friday        = 4
   Saturday      = 5
   Sunday        = 6
)
 
func main() {
   fmt.Println(Monday)
   fmt.Println(Tuesday)
   fmt.Println(Wednesday)
   fmt.Println(Thursday)
   fmt.Println(Friday)
   fmt.Println(Saturday)
   fmt.Println(Sunday)
}

Output

$ go run main.go
0
1
2
3
4
5
6

 

Define enums using iota

Iota is an identifier in Go that is used with constants that help simplify constant definition. This prevents developers from writing values manually which has proven to be error prone. It defines constants by auto-incrementing the numbers. It represents  successive integer values like 0, 1,2,3,4,5 …

Advertisement

When defining custom enum types follow the below steps:

  1. Declare a new custom type e.g campusDirection (int type)
  2. Declare constant as related using iota

Example

package main
 
import "fmt"
 
type campusDirection int64
 
const (
   North campusDirection = iota // 0
   South                 = iota // 1
   East                  = iota // 2
   West                  = iota // 3
)
 
func main() {
   fmt.Println(North)
   fmt.Println(South)
   fmt.Println(East)
   fmt.Println(West)
}

Explanation

In the above example , we define a custom type campusDirection of type int64.  We also define a set of constant values, North , South ,East and West of type compusDirection. For each constant, we assign an iota keyword.  Each constant will have a value assigned to from 0 upto to the last one. Therefore North=0, South = 1, East =2 and South= 3.It is worth mentioning that each constant is of type campusDirection and each executes their own iota + 1. The iota increases by 1 after each line except empty and comment lines

Output

$ go run main.go
0
1
2
3

This example can be rewritten without assigning all constant the iota keyword to every constant. Instead the first constant gets assigned the iota keyword and the rest of the constant will be assigned successive constant values.

Example

package main
 
import "fmt"
 
type CampusDirection int64
 
const (
   North CampusDirection = iota // 0
   South // 1
   East // 2
   West // 3
)
 
func main() {
   fmt.Println(North) // 0
   fmt.Println(South) // 1
   fmt.Println(East) // 2
   fmt.Println(West) // 3
}

 

Creating enums starting with 1

By default, iota assigns constant  values starting from 0. This default behavior can be changed by adding a value that you want the iota to start with.

Example

package main
 
import "fmt"
 
type CampusDirection int64
 
const (
   North CampusDirection = iota + 1 // 1
   South                            // 2
   East  = iota + 5                 // 7
   West                             // 8
)
 
func main() {
   fmt.Println(North)
   fmt.Println(South)
   fmt.Println(East)
   fmt.Println(West)
}

Explanation

In the above example, we use the iota + int value syntax to define the initial value of an iota. In this example, we set the initial value for  the set of constant values to 1 using North campusDirection = iota + 1 . We also go ahead and increase the iota value by 5 using the East = iota + 5 syntax.

Output

$ go run main.go
1
2
7
8

 

Creating enums by multiplying

The initial value of enums can be changed by multiplying the iota with an integer. In this example we will demonstrate multiplication with iota.

Example

package main
 
import "fmt"
 
type campusDirection int64
 
const (
   North campusDirection = iota + 1    // 0 + 1 = 1
   South                 = iota * 1000 // 1 * 1000 = 1000
   East                                // 2 * 1000 = 2000
   West                                // 3 * 1000 = 3000
)
 
func main() {
   fmt.Println(North)
   fmt.Println(South)
   fmt.Println(East)
   fmt.Println(West)
}

Output

$ go run main.go
1
1000
2000
3000

 

Resetting iota

An enum can be reset back to initial value zero by re-decalaring iota more than once in the code.

Example

package main
 
import "fmt"
 
type campusDirection int64
 
const (
   North campusDirection = iota + 1000 // 0 + 1000 = 1000
)
 
// Resetting constants
const (
   South campusDirection = iota // 0
   East                         // 1
   West                         // 2
)
 
func main() {
   fmt.Println(North)
   fmt.Println(South)
   fmt.Println(East)
   fmt.Println(West)
}

Explanation

In the above example, we define constants using iota two times. In the first constant definition, the North constant of type campusDirection has its value set to 1000 (iota + 1000).

Next, we define another set of constant values of type campusDirection starting from the iota initial value of 0. This resets the iota value from 1000 to 0.

Output

 go run main.go
1000
0
1
2

 

Skipping values in a list of constants

Upto this point we know how to define successive constants using iota. It is also possible to skip a value assigned by the iota using the blank identifier.

Example

package main
 
import "fmt"
 
type campusDirection int64
 
const (
   North campusDirection = iota + 1 // 0 + 1 = 1
   _                                // skipping 2
   South                            // 3
   East                             // 4
   West                             // 5
)
 
func main() {
   fmt.Println(North)
   fmt.Println(South)
   fmt.Println(East)
   fmt.Println(West)
}

Explanation

In the above example, we define campus direction constant values using enums. In the list of constants we add a blank identifier after the North constant variable.

This blank identifier (_) will be skipped when the iota will be assigning values to the campus direction constants. In our example, number 2 is skipped in assignment of cosntants.

Output

$ go run main.go
1
3
4
5

 

Defining common behavior

Since we have our own custom type defined (campusDirection), we can add a receiver function to it so that all the constants have the same behavior. Let us define a function called toString() that converts the int values assigned by iota to string representation.

Example

package main
 
import "fmt"
 
type campusDirection int64
 
func (c campusDirection) toString(index campusDirection) string {
   return []string{"North", "East", "West", "South"}[index]
}
 
const (
   North campusDirection = iota + 1 // 1
   South                            // 2
   East                             // 3
   West                             // 4
)
 
func main() {
   var direction = North
   n := direction.toString(0)
   e := direction.toString(1)
   w := direction.toString(2)
   s := direction.toString(3)
   fmt.Println(n)
   fmt.Println(e)
   fmt.Println(w)
   fmt.Println(s)
}

Explanation

In the above example, we define a receiver function on the campusDirection type. This function is called toString() and it takes the index int of the constant that you want to access. In the main function, we declare a direction variable of type campusDirection.  We access individual direction using the toString() method on the campusDirection instance(direction)

Output

$ go run main.go 
North
East
West
South

 

When not to use iota

Do not use iota for a list of constants that are predefined. These constants can be for example HTTP status codes. The below code sample is NOT acceptable.

Example

package main
 
import "fmt"
 
type statusCode int64
 
const (
   statusOK     statusCode = iota 
   statusCreated            = 201 
   serverError             = 500  
   NotFound                = 404  
)

 

Summary

This article covers working with enums in Go. It covers enum definitions, using iota , setting initial values for iota ,resetting iota , skipping values in iota and when not to use iota.

 

References

go-enum

 

Categories GO

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

2 thoughts on “Golang Enum Tutorial [With Examples]”

  1. In the example code for “Creating enums by multiplying” there is a line ” East // 2 * 1000 = 4000″.

    I’m new to `go`, but this looks… odd.

    -E

    Reply
    • Thanks for highlighting the typo. In the next line the output was correct but in the comments 4000 was wrongly written instead of 2000.

      Reply

Leave a Comment