July 8th, 2024

Enums in Go

This article explores emulating enums in Go, a language lacking native support. It covers defining custom types with strings or integers, utilizing the iota keyword, implementing interfaces, custom marshalling, and tools like go-enum.

Read original articleLink Icon
Enums in Go

This article discusses how to emulate enums in Go, a language that does not have native enum support. It explains the concept of enums and provides examples of how to define custom types using strings or integers. The use of the iota keyword to simplify enum declarations is also demonstrated. The article covers implementing the Stringer interface to get member names, custom marshalling and unmarshalling for enums, and reducing boilerplate code with tools like go-enum. It also addresses improving type safety by using structs and alternative approaches to define enums in Go. The author shares personal preferences and experiences regarding enum implementation in Go. Overall, the article serves as a comprehensive guide for working with enums in Go, offering various techniques and considerations for developers.

Link Icon 13 comments
By @weavie - 3 months
The problem isn't so much the lack of enums, it's more that there is no way to do exhaustive pattern matching at compile time. I have seen production systems go down because someone added a variant to an 'enum' but failed to handle that new variant everywhere.
By @daghamm - 3 months
I'm implementing a somewhat complex software in both Go and Rust.

The Rust version is bith shorter and more readable - and probably more efficient - thanks to Rust enums and Rust error handling. I don't understand why golang doesn't copy Rust here. The error handling in particular could be a very simple change.

I am not a huge fan of go:generate and similar projects. They add a level of unknown that goes against the core Golang design values.

By @barnabee - 3 months
I’ve found the enumer [0] library does the job of generating usable helpers without too much pain or any obvious downsides. The ability to generate JSON [un]marshallers is particularly handy.

Still, the lack of enums and enum/sum types remains by far my biggest gripe about Go.

[0] https://github.com/dmarkham/enumer

By @bborud - 3 months
Enums in Go are not good. Code generation just makes it worse. Both because code generation has a bad smell and because nobody can agree on how to do enums in Go so we just end up with lots of diverging solutions.

Go 2 needs to have more usable enums. And while I'm not a big fan of "adding more stuff" to languages, it wouldn't hurt Go to learn a couple of things from Rust.

By @dgb23 - 3 months
I recently wrote a little tokenizer in Go.

The data structure for a token that makes most intuitive sense to me is a tagged union.

So I defined an „const iota“-style enum. Stuck it into a struct that has the appropriate fields to cover all the cases and it was fine.

Having some syntax sugar for tagged unions would be nice. Having exhaustiveness checks if you switch over them, could be useful in some cases.

But that’s not where my mental energy went at all.

Reading the bytes (runes) efficiently and correctly into the data structure however is the part that needs focus. Once the data is in shape, I‘m not „worried“ at all anymore. Sure a bit of extra support is nice, but also kind of superficial.

Also going further, dispatching on them is again never the tricky part. It’s handling the cases correctly and efficiently that has my focus.

In Clojure, a common thing is to write multimethods that dispatch on (namespaced) keywords. Similar in spirit and structure, but each method might now reside in a different namespace or not even be written by you. But I have never worried about exhaustive matching or similar. What’s in the method bodies is the important part.

By @altug - 3 months
I really miss value enums from Rust while working with Go, but overall I find Go more intuitive. Didn't know there was a way of auto-generating with stringer, so thanks for the information!
By @pjmlp - 3 months
Besides the iota dance hack of "enums" in Go, apparently Go 1.23 is going to bring another one, magic fields.

https://pkg.go.dev/structs@master

What more sane languages would use attributes for, Go 1.23 will do it like this,

    type myStruct struct {
        _  struct.HostLayout 
    }
Lovely design.
By @asabla - 3 months
I wonder if go ever will get some sort of enum type? Or if int/string based types will be the goto way?
By @techn00 - 3 months
By @akira2501 - 3 months
Use a slice of strings?

    type Color int
    const (
        Red Color = iota
        Green
        Blue
    )

    var Colors = []string{ "Red", "Green", "Blue" }
Now (Colors[Red] == "Red") and (slices.Index(Colors, "Green") == Green).
By @nikolayasdf123 - 3 months
+1. Here is another alternative. I find this generator more lightweight and better syntax (generated benchmarks and tests are also nice):

https://github.com/nikolaydubina/go-enum-encoding

By @candiduslynx - 3 months
Oh, the missing wonders of `[...]`: https://go.dev/play/p/GlVp_z3IOEe
By @witx - 3 months
I can't take this language seriously. No enums, letter cases defining if something is "public" or "private", generics as an after-thought. To name just a few