在Go中表示枚举的惯用方式是什么?
我试图表示一个简化的染色体,它由N个碱基组成,每个碱基只能是{A, C, T, G}
。
我想用enum来形式化约束,但是我想知道在Go中模拟枚举的最习惯的方式是什么。
从语言规范引用:Iota
在一个常量声明中,预先声明的标识符iota代表连续的非类型整数常量。 只要保留字const在源中出现并在每个ConstSpec后递增,它就被重置为0。 它可以用来构造一组相关的常量:
const ( // iota is reset to 0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const (
a = 1 << iota // a == 1 (iota has been reset)
b = 1 << iota // b == 2
c = 1 << iota // c == 4
)
const (
u = iota * 42 // u == 0 (untyped integer constant)
v float64 = iota * 42 // v == 42.0 (float64 constant)
w = iota * 42 // w == 84 (untyped integer constant)
)
const x = iota // x == 0 (iota has been reset)
const y = iota // y == 0 (iota has been reset)
在ExpressionList中,每个iota的值是相同的,因为它只在每个ConstSpec后递增:
const (
bit0, mask0 = 1 << iota, 1<<iota - 1 // bit0 == 1, mask0 == 0
bit1, mask1 // bit1 == 2, mask1 == 1
_, _ // skips iota == 2
bit3, mask3 // bit3 == 8, mask3 == 7
)
这最后一个例子利用了最后一个非空表达式列表的隐式重复。
所以你的代码可能是这样的
const (
A = iota
C
T
G
)
要么
type Base int
const (
A Base = iota
C
T
G
)
如果你希望base是一个int类型的独立类型。
参考jnml的答案,可以通过完全不导出Base类型来阻止Base类型的新实例(即,将其写成小写字母)。 如果需要,你可以创建一个可导出的接口,它有一个返回基类型的方法,这样这个接口可以用在处理基类的外部函数中,即
package a
type base int
const (
A base = iota
C
T
G
)
type Baser interface {
Base() base
}
// every base must fullfill the Baser interface
func(b base) Base() base {
return b
}
func(b base) OtherMethod() {
}
package main
import "a"
// func from the outside that handles a.base via a.Baser
// since a.base is not exported, only exported bases that are created within package a may be used, like a.A, a.C, a.T. and a.G
func HandleBasers(b a.Baser) {
base := b.Base()
base.OtherMethod()
}
// func from the outside that returns a.A or a.C, depending of condition
func AorC(condition bool) a.Baser {
if condition {
return a.A
}
return a.C
}
在主包中, a.Baser
现在就像一个枚举。 只有在一个包中你可以定义新的实例。
从Go 1.4开始, go generate
工具与stringer
命令一起被引入,这使得enum可以轻松地调试和打印。