Это правда, что приведенные выше примеры использования const
и iota
являются наиболее идиоматическими способами представления примитивных перечислений в Go. Но что, если вы ищете способ создания более полнофункционального перечисления, подобного типу, который вы видели бы на другом языке, таком как Java или Python?
Очень простой способ создать объект, который начинает выглядеть и чувствовать себя как строковое перечисление в Python:
package main
import (
"fmt"
)
var Colors = newColorRegistry()
func newColorRegistry() *colorRegistry {
return &colorRegistry{
Red: "red",
Green: "green",
Blue: "blue",
}
}
type colorRegistry struct {
Red string
Green string
Blue string
}
func main() {
fmt.Println(Colors.Red)
}
Предположим, вам также нужны некоторые служебные методы, например Colors.List()
, и Colors.Parse("red")
. И ваши цвета были более сложными и должны были быть структурой. Тогда вы можете сделать что-то вроде этого:
package main
import (
"errors"
"fmt"
)
var Colors = newColorRegistry()
type Color struct {
StringRepresentation string
Hex string
}
func (c *Color) String() string {
return c.StringRepresentation
}
func newColorRegistry() *colorRegistry {
red := &Color{"red", "F00"}
green := &Color{"green", "0F0"}
blue := &Color{"blue", "00F"}
return &colorRegistry{
Red: red,
Green: green,
Blue: blue,
colors: []*Color{red, green, blue},
}
}
type colorRegistry struct {
Red *Color
Green *Color
Blue *Color
colors []*Color
}
func (c *colorRegistry) List() []*Color {
return c.colors
}
func (c *colorRegistry) Parse(s string) (*Color, error) {
for _, color := range c.List() {
if color.String() == s {
return color, nil
}
}
return nil, errors.New("couldn't find it")
}
func main() {
fmt.Printf("%s\n", Colors.List())
}
На этом этапе, конечно, это работает, но вам может не понравиться то, как вы должны повторно определять цвета. Если в этот момент вы захотите устранить это, вы можете использовать теги в своей структуре и поразмышлять над ее настройкой, но, надеюсь, этого достаточно, чтобы охватить большинство людей.