В Go есть идиоматический способ объявления перечислений, который многие (включая меня) хвалят за его простоту:

type Day int
const (
   Monday Day = 1 + iota
   Tuesday
   Wednesday
   Thursday
   Friday
   Saturday
   Sunday
)

Другие языки обычно имеют больше возможностей для типов enum, например в Java:

public enum Day {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday 
}

И тогда вы можете использовать такие функции, как:

for (Day day: Day.values()) {
    if (day == Day.Monday) {
       System.out.printf("Monday is day number %d\n", day.ordinal());
    }
    System.out.printf("Day of the week: %s\n", day);
}

В C# вы можете воспользоваться аналогичными проверками безопасности типов и немного другим синтаксисом для базового типа:

enum Days : byte {Monday=1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

Давайте теперь еще раз взглянем на то же перечисление в Go, сосредоточив внимание на том, что мы могли бы использовать:

type Day int // a String() method for each value, so that we can printf it during development/logging?
const (
   Monday Day = 1 + iota // more complex types maybe?
   Tuesday
   Wednesday
   Thursday
   Friday
   Saturday
   Sunday
   // boundary check so that I cannot inadvertently create an 8th day of the week?
)
// array/slice of allowed values?

Обсуждая с другими программистами Go, я пришел к идее использовать несколько более строгий синтаксис для перечислений Go, (ab)используя переключатели типов и чудеса шаблонизации (с помощью go:generate), результатом чего является go- роды.

Сгенерированный код для этого примера будней с go-genums (некоторые части отредактированы для простоты):

package main

// *** generated with go-genums ***

// DayEnum is the the enum interface that can be used
type DayEnum interface {
	String() string
	Value() dayEnum
	uniqueDayMethod()
}

// dayEnumBase is the internal, non-exported type
type dayEnumBase struct{ value dayEnum }

// Value() returns the enum value
func (eb dayEnumBase) Value() dayEnum { return eb.value }

// String() returns the enum name as you use it in Go code,
// needs to be overriden by inheriting types
func (eb dayEnumBase) String() string { return "" }

// ... [redacted declaration of a type+methods for each allowed enum value]

var internalDayEnumValues = []DayEnum{
	Sunday{}.New(),
	Monday{}.New(),
	Tuesday{}.New(),
	Wednesday{}.New(),
	Thursday{}.New(),
	Friday{}.New(),
	Saturday{}.New(),
}

// DayEnumValues will return a slice of all allowed enum value types
func DayEnumValues() []DayEnum { return internalDayEnumValues[:] }

// NewDayFromValue will generate a valid enum from a value, or return nil in case of invalid value
func NewDayFromValue(v dayEnum) (result DayEnum) {
	switch v {
	case daySunday:
		result = Sunday{}.New()
	case dayMonday:
		result = Monday{}.New()
	case dayTuesday:
		result = Tuesday{}.New()
	case dayWednesday:
		result = Wednesday{}.New()
	case dayThursday:
		result = Thursday{}.New()
	case dayFriday:
		result = Friday{}.New()
	case daySaturday:
		result = Saturday{}.New()
	}
	return
}

// ... [redacted]

Результирующий сгенерированный код перечисления, тем не менее, длиннее и сложнее, но вам не нужно вводить его, так как он генерируется автоматически; среди функций, добавленных на этом этапе генерации кода, лично мне больше всего нравится возможность использовать переключатели типов для оценки перечисления:

day := Monday{}.New()
switch day.(type) {
    case Monday:
        fmt.Println("It's", day)
    default:
        panic("It's not Monday!")
}

Обратите внимание, что переключение типа значения интерфейса по-прежнему довольно эффективно, так как оно не будет разыменовывать фактическое значение (будь то целое число или большая структура), а вместо этого будет использовать внутренний идентификатор типа Go.

И последнее, но не менее важное: с помощью go-genums вы можете использовать объявление структур для вашего перечисления и автоматически сгенерированные проверяющие фабричные методы, и вы не теряете возможности прямого сравнения переменных перечисления; вы можете прочитать больше и поиграть с ним на странице проекта github.