Home > Articles > Programming

A Go Primer

  • Print
  • + Share This
This chapter is from the book

Creating Enumerations

From: enum.go

4 const (
5   Red             = (1<<iota)
6   Green           = (1<<iota)
7   Blue, ColorMask = (1<<iota), (1<<(iota+1))-1
8 )

There are several places in Go where it is obvious that someone has spent a lot of thought designing exactly the right syntax for most common uses of a language feature. Enumeration constants are the most obvious example of this attention to detail.

There is no divide between constants and enumerations in Go. This mirrors their implementation in C, where enumerated types can be used interchangeably with integers. Groups of constants within the same declaration in Go are used for enumerations.

There are two common uses for enumerated types. The first is defining a set of mutually-exclusive options. The second is defining a set of overlapping flags. Typically, you’ll use a sequence of numbers for the first and a sequence of powers of 2 for the second. You can then create a bitfield by bitwise-oring a combination of enumeration values together.

In C, and most other languages with enumerated types, you need to explicitly provide the numerical values for the second type of enumeration. The first will be automatically numbered by the compiler.

Go provides a much more flexible mechanism for defining enumerations. The iota predeclared identifier is similar to the GNU C __COUNTER__ preprocessor macro, but it’s more powerful. It is an integer constant expression. In a normal program scope, it evaluates to zero, but in the scope of a constant declaration it is initially zero but then incremented on each line where it is used.

Unlike __COUNTER__, iota is scoped. It is zero on the first line of the group in this example, and will always be zero in the first line of this group, irrespective of how it is used elsewhere. If you have multiple const groups in a single source file, then iota will be zero at the start of each of them.

The example at the start of this section shows how to declare a group of constants for use as an enumerated type. This simple example shows the low 3 bits of a bitfield being used to store three flags indicating the presence of three color values. The ColorMask constant is defined to provide the value that must be bitwise-and’d with an integer to give the three color flags.

It’s possible to reference constants from other constant declarations, so you can combine this kind of declaration easily. For example, you could provide another constant declaration describing another group of flags within a set, and then extend this declaration to use them in the next few bits of the bitfield.

Similarly, you can extend existing constant declarations by inserting another iota expression earlier. This will then renumber all subsequent values, so it’s important to be careful when the constants are part of a binary interface.

Constants—and therefore enumerations—in Go are not limited to integers. Other types can be specified in the same way. The enum.go example also shows the declaration of the complex constant i, with the same definition as in mathematics.

From: enum.go

10 const (
11   i complex128 = complex(0, 1)
12 )
  • + Share This
  • 🔖 Save To Your Account