How to: enum in GOlang

An enum is a set of values, usually of the same type (like string or integer), and you can use them to limit allowed values to for example functions.

A traffic light for example could have an enum that consists of the different signal colours like ["red", "yellow", "green"] or ["stop", "stop", "go soon", "go now"] depending on implementation.

TypeScript

In TypeScript we have access to enums as a first class concept and they are type safe.

We can define them either with numeric indexes


enum IsItTheWeekend {
  No, // equivalent to No = 0
  Yes, // equivalent to Yes = 1
}

console.log(IsItTheWeekend.No) // 0

You can also define strings for example to make sure that only certain values are allowed and not just any string.

enum Weekday {
  Monday = "Monday",
  Tuesday = "Tuesday",
  Wednesday = "Wednesday",
  Thursday = "Thursday",
  Friday = "Friday",
  Saturday = "Saturday",
  Sunday = "Sunday",
}

function IsItTheWeekend(day: Weekday) {
  if (day === Weekday.Saturday || day === Weekday.Sunday) {
    console.log("Ladies and gentlemen, it's the weekend!");
    return;
  }
  console.log("Back to work, zug zug.")
}

function main() {
  IsItTheWeekend(Weekday.Friday);
  IsItTheWeekend(Weekday.Saturday);

  // Will produce a TypeScript error on build:
  // enums.ts:26:17 - error TS2345: Argument of type '"Wednesday"' is not assignable to parameter of type 'Weekday'
  IsItTheWeekend("Wednesday");
}

main();

Even though it causes errors at build time, you can still run the above code with node by using node --experimental-transform-types enums.ts with the following output:

Back to work, zug zug.
Ladies and gentlemen, it's the weekend!
Back to work, zug zug.

More enum References

GOlang

Enums are a tricky subject in GO. There is no type safe vanilla implementation, however there are some community implementations that make them more similar to other languages.

In GO we can define an enum as a const with either auto-incrementing numbers:

package main

import "fmt"

type Weekday int

const (
  Monday  Weekday = iota // 0
  Tuesday                // 1
  Wednesday
  Thursday
  Friday
  Saturday
  Sunday
)

func main() {
  fmt.Println(Monday)  // 0
  fmt.Println(Tuesday) // 1
}

We can also define string values for finite sets of known values. We should use this cautiously, as we can not rely on the compiler to check if a value is present even if we write a function that should only accept values from an enum.

See the example below, to ensure type safety we either need to check with an interface of the type like IsValid or move the check to a function like GetWeekday.

package main

import (
  "errors"
  "fmt"
)

type Weekday string

const (
  Monday    Weekday = "Monday"
  Tuesday   Weekday = "Tuesday"
  Wednesday Weekday = "Wednesday"
  Thursday  Weekday = "Thursday"
  Friday    Weekday = "Friday"
  Saturday  Weekday = "Saturday"
  Sunday    Weekday = "Sunday"
)

func (d Weekday) IsValid() bool {
  switch d {
  case Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday:
    return true
  default:
    return false
  }
}

func GetWeekday(d Weekday) (Weekday, error) {
  if d.IsValid() {
    return d, nil
  }
  return "", errors.New("invalid weekday")
}

func IsItTheWeekend(d Weekday) {
  fmt.Println("function argument: ", d)

  if !d.IsValid() {
    fmt.Printf("%s is not a valid weekday.\n", d)
    return
  }

  if d == Saturday || d == Sunday {
    fmt.Println("Ladies and gentlemen, it's the weekend.")
  } else {
    fmt.Println("Back to work, zug zug.")
  }
}

func main() {
  IsItTheWeekend(Friday)
  IsItTheWeekend(Saturday)

  // does not cause a compile time error
  IsItTheWeekend("wednesday")

  myWeekday, err := GetWeekday("Friyay")
  if err != nil {
    fmt.Printf("Error: %s is not a valid weekday.\n", myWeekday)
    return
  }

  IsItTheWeekend(myWeekday)
}

Output:

function argument:  Friday
Back to work, zug zug.
function argument:  Saturday
Ladies and gentlemen, it's the weekend.
function argument:  wednesday
wednesday is not a valid weekday.
Error:  is not a valid weekday.

More go-enum References