Enums in Go

If you’ve ever spoken with me about programming, it’s very likely that my affinity for the Go programming language has come up. Go1 is a powerful and yet, incredibly simplistic language for doing everything from web servers to systems programming.

The team behind Go is incredibly careful and selective when it comes to adding new features to the language, and because of this we quickly find that the language doesn’t offer a syntax for Enumerations (or enums).

What’s an Enum(eration)?

For those that don’t know, an enumeration is a distinct type that consists of a set of named constants called the enumerator list. It’s essentially a good way to produce a set of human readable values.

Let’s create a simple example of enums in action using C#. We’re going to have an enum that contains the seasons of a year and a DescribeSeason function that relies on a specific season to be given.

You can try this code out on repl.it

using System;

enum Season {
  Winter, // 0
  Spring, // 1
  Summer, // 2
  Fall,   // 3
}

class MainClass {

  public static void Main (string[] args) {
    Console.WriteLine(DescribeSeason(Season.Summer));
  }
  
  private static string DescribeSeason(Season season) {
    switch (season) {
      case Season.Winter:
        return "Brrrr... It's cold!";
      case Season.Spring:
        return "Oh pretty flowers!  AHHH a bee!";
      case Season.Summer:
        return "Time to hit the beach!";
      case Season.Fall:
        return "The leaves! They're dying!";
      default:
        return "How did you get here?";
    }
  }
}

No Native Enums?

At first this seemed like an odd choice to me that the Go team wouldn’t include such a useful feature for a typed language. However, upon digging a bit deeper, I quickly discovered why there is no enum keyword:

You can create primitives types by aliasing other primitive types.

In Go, you can alias existing types using the syntax:

type NewType ExistingType

If we think about the most common variant of an enum is, an integer, we can easily specify our core type of enumeration. Let’s try and replicate our C# example from above, but in Go.

You can try out the Go version for yourself on repl.it

package main

import "fmt"

type Season int

const (
  Season_Winter Season = 0
  Season_Spring Season = 1
  Season_Summer Season = 2
  Season_Fall   Season = 3
)

func main() {
  fmt.Println(DescribeSeason(Season_Summer))
}

func DescribeSeason(season Season) string {
  switch (season) {
    case Season_Winter:
      return "Brrrr... It's cold!"
    case Season_Spring:
      return "Oh pretty flowers!  AHHH a bee!"
    case Season_Summer:
      return "Time to hit the beach!"
    case Season_Fall:
      return "The leaves! They're dying!"
    default:
      return "How did you get here?"
  }
}

You’ll likely notice that our enum isn’t actually it’s “object-style type” like in C#, C++, Java, etc… But, by using named constants we are able to achieve the same result.

Adding iota

As one final change, let’s remove the need of manual value assignment to our custom Season enumeration type. We can do this using iota, which is a quirky2, universal counter that is provided natively by Go.

Though the syntax is bit funky for a couple of reasons, maintaining the enumeration down the road becomes less of a hassle as we don’t need to manually reassign or reorder values.

const (
  Season_Winter Season = iota + 1
  Season_Spring
  Season_Summer
  Season_Fall
)

  1. Go is often referred to as Golang and I might use both terms interchangably. ↩︎

  2. Rather than get into iota in depth in this article, I’m just going to point you Golang’s own wiki page on GitHub. ↩︎