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.