DEV Community

Cover image for Mastering ENUMs in Go

Mastering ENUMs in Go

Image by Hans-Peter Gauster from Unsplash

Let's say we are building an E-commerce API that will receive several orders, each order process has several statuses such as Pending, Processed, Shipped, Delivered, Cancelled. And our application receives input strings which will be stored in the database, for example the status is Processed, received Process, Processing or something else that causes data inconsistencies. Here Enum has an important role.

In Golang enums unlike other languages ​​such as Java or C# which offer built-in support for enums, Go takes a different approach. In Go, enums are not a native language feature, but developers have several techniques that can be used to achieve similar functionality.

Understanding Enum

In Golang, enums (short for enumerations) provide a way to represent a set of named constants. Although Go does not have built-in enum types like some other languages, developers can emulate enum-like behavior using constants or custom types. Let's discuss the purpose and syntax of enums in Go:

Objective

  • Readability and Maintainability: Enums make code more readable and easy to understand by giving meaningful names to specific values. This increases the maintainability of the code because the purpose of each constant becomes easier to understand.

  • Type Safety: Enums help enforce type safety by restricting variables to a predefined set of values. This reduces the possibility of runtime errors caused by using incorrect values.

Create Enums

Here we will discuss step by step how to create an enum in Golang, so that it is easy to understand at each stage we will explain the meaning of the code we write.

Create a New Type

The first thing we will do is create a new type for the enum we need. The method is quite easy, we only need to use the keyword type and followed by the name of the type here with the name StatusOrder and the type here we define the type integer like this:

type StatusOrder int
Enter fullscreen mode Exit fullscreen mode

Well, just make it easy.

Define constant ENUM

With the new type that we have created, now is the time for us to define some of the order statuses that we have with constants. Where we define the type StatusOrder which we create as the type, like this:

const (
    Pending StatusOrder = iota
    Processed
    Shipped
    Delivered
    Cancelled
)
Enter fullscreen mode Exit fullscreen mode

Maybe you ask, what is the keyword iota? This keyword makes GO assign a value of 0 to the first constant and then increase the value by 1 sequentially for each subsequent constant. This makes it easier for us rather than defining the values ​​manually 1 by 1. About iota you can read here.

Function Strings

The next step we will take is to create a String function that is used to represent each string value from the StatusOrder enum.

func (s StatusOrder) String() string {
    switch s {
    case Pending:
        return "Pending"
    case Processed:
        return "Processed"
    case Shipped:
        return "Shipped"
    case Delivered:
        return "Delivered"
    case Cancelled:
        return "Cancelled"
    default:
        return "Unknown"
    }
}
Enter fullscreen mode Exit fullscreen mode

Does the function name have to be String? We'll discuss it at the end.

Testing

Now we will carry out testing, the last code we will write is, function main and in it we print the results using the help of the fmt package. yes.

func main() {

    processed := Processed
    fmt.Printf("Order Status: %s (%d)\n", processed, processed)

    pending := Pending
    fmt.Printf("Order Status: %s (%d)\n", pending, pending)

}
Enter fullscreen mode Exit fullscreen mode

Now the complete code can be seen here.

Of course, we carry out the last step and we will see the results like this:

Image description

Fmt Stringer

The question may arise, why is the String function also called when we call the enum constant?. The answer is because we use the fmt package. The fmt package explicitly uses the fmt.Stringer interface to process types that implement the String() method. So, if you don't use fmt, the String() method will not be called automatically. To explain more, you can explore in more detail here.

Conclusion

Although Golang does not offer native enum types, the techniques we learn here are often used in building applications with Golang. And for the type itself, we can freely use other types, not just integer. By utilizing this technique, readability, ease of maintenance and security can be significantly improved.

Maybe there are some points explained above that you feel are lacking, we can discuss them in the comments column below. Hope it helps 👋.

Reading References

Top comments (0)