Đúng là các ví dụ trên về việc sử dụng const
và iota
là những cách thành ngữ nhất để biểu thị các enum nguyên thủy trong Go. Nhưng điều gì sẽ xảy ra nếu bạn đang tìm cách tạo ra một enum có đầy đủ tính năng tương tự như loại bạn thấy trong một ngôn ngữ khác như Java hoặc Python?
Một cách rất đơn giản để tạo một đối tượng bắt đầu trông và cảm thấy giống như một chuỗi enum trong Python sẽ là:
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)
}
Giả sử bạn cũng muốn một số phương thức tiện ích, như Colors.List()
, và Colors.Parse("red")
. Và màu sắc của bạn phức tạp hơn và cần thiết để trở thành một cấu trúc. Sau đó, bạn có thể làm một cái gì đó như thế này:
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())
}
Tại thời điểm đó, chắc chắn rằng nó hoạt động, nhưng bạn có thể không thích cách bạn phải xác định lại màu sắc. Nếu tại thời điểm này, bạn muốn loại bỏ điều đó, bạn có thể sử dụng các thẻ trên struct của mình và thực hiện một số phản xạ lạ mắt để thiết lập nó, nhưng hy vọng điều này là đủ để bao phủ hầu hết mọi người.