Implementing Enums in Golang

18 Dec 2021
Implementing Enums in Golang

An enum (aka enumerator) is a data type consisting of a set of named constant values. Enums are a powerful feature with a wide range of uses. Go doesn’t support enums natively. There are ways to define enums a bit differently compared to other programming languages like Java. A very simple example of enum can be the 4 directions.

enum Direction would have 4 values:

- North
- West
- South
- East

Define Enums In Go

Let’s try to understand enum with an example. An enum for CardSuit has 4 possible values and it can be defined as:

// Way to implement enum
type CardSuit int

const (
  Spades  CardSuit = 0
	Diamond CardSuit = 1
	Heart   CardSuit = 2
	Club    CardSuit = 3
)

Problem

What if the set of values that you want to be a part of enum is big? It’s not feasible to manually maintain numbers. Another problem with this approach is handling the enum numeric values explicitly when you remove one or more values.

Solution: Using iota

To solve the problem above, Golang provides us with a keyword iota that is a built-in, predeclared identifier that represents successive untyped integer constants. The iota starts from zero and auto-increments as more values are added. Once you’ve defined iota in your constant, it is not required with further values. You can read more about iota here.

type CardSuit int

const (
	Spades CardSuit = iota
	Diamond
	Heart
	Club
)

This works exactly as before but now you can remove or extend your enum without updates through out your code. But you must have notices that we have defined Weekday as int but what if we need a float or a string value for each enum type. We can always define a Float or String to solve this. Let’s add a method to return string values for our Weekday enum.

package main

import "fmt"

type CardSuit int

const (
	Spades CardSuit = iota
	Diamond
	Heart
	Club
)

// returns corresponding string value to the CardSuit enum
func (c CardSuit) String() string {
	switch c {
	case Spades:
		return "Spades ♤"
	case Diamond:
		return "Diamond ♢"
	case Heart:
		return "Heart ♥"
	case Club:
		return "Club ♧"
	}
	return "Unknown card suit"
}

func main() {
	// define day of type CardSuit (enum)
	var suit CardSuit
	// initializing the day
	suit = Heart
	fmt.Printf("Suit is %s", suit.String())
}

In the above case, switch case seems to be a lot of work. Since we have iota as index we could use a string slice directly.

func (c CardSuit) String() string {
	return []string{"Spades", "Diamond", "Heart", "Club"}[c]
}

Points to Remember

  • You can use enum to include default/unknown values in enum as well and handle them in further implementation.

    const (
    	Unknown CardSuit = iota
      Spades
    	Diamond
    	Heart
    	Club
    )
    
  • Using iota some values can be skipped when defining enum types. In the example enum below, there is no value defined for value 2.

    type Vehicle int
    
    const(
      Car Vehicle = iota
      Bike
      _
      Truck
      Ship
    )
    
  • Another usecase could be to have different increment counter instead of 1.

    const (
        Success = iota        // iota = 0 initially
        Fail = iota + 2       // iota = 1 so 1 + 2 = 3
        Pending = iota * 5    // iota = 2 so 2 * 5 = 10
    )
    
  • Instead of defining enums as int or string, they can be defined as structs. An example for struct based enum in Go would look like this:

    type Vehicle struct {
        name   string
        wheels int
    }
    
    func (v Vehicle) String() string {
        return v.name
    }
    
    func (v Vehicle) Wheels() int {
        return v.wheels
    }
    
    var (
        Unknown = Vehicle{"", 0}
        Car     = Vehicle{"car", 4}
        Bike    = Vehicle{"bike", 2}
        Ship    = Vehicle{"ship", 0}
    )
    
    func main() {
        car := Car
        fmt.Printf("Wheels in %s: %v", car.String(), car.Wheels())
    }
    

Resources

Popular Go Articles you make like

Books to learn Golang


I hope you learned something new. Feel free to suggest improvements ✔️

I share regular updates and resources on Twitter. Let’s connect!

Keep exploring 🔎 Keep learning 🚀

Liked the content? Do support :)

Paypal - Mohit Khare
Buy me a coffee