我试图表示一个简化的染色体,它由N个碱基组成,每个碱基只能是{a, C, T, G}中的一个。
我想用枚举形式化约束,但我想知道在Go中模拟枚举的最惯用的方式是什么。
我试图表示一个简化的染色体,它由N个碱基组成,每个碱基只能是{a, C, T, G}中的一个。
我想用枚举形式化约束,但我想知道在Go中模拟枚举的最惯用的方式是什么。
当前回答
引用语言规范:Iota
在常量声明中,预先声明的标识符iota表示连续的无类型整型常量。当保留字const出现在源代码中时,它被重置为0,并且在每个ConstSpec之后递增。它可以用来构造一组相关常数:
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
)
or
type Base int
const (
A Base = iota
C
T
G
)
如果你想让base是一个独立于int的类型。
其他回答
下面是一个示例,当有许多枚举时,它将被证明是有用的。它使用了Golang中的结构,并借鉴了面向对象原则(Object Oriented Principles),将它们紧密地捆绑在一起。添加或删除新的枚举时,底层代码都不会更改。流程如下:
定义枚举项的枚举结构:EnumItem。它有一个整数和字符串类型。 将枚举定义为枚举项列表:Enum 为枚举构建方法。其中包括: 枚举。Name(index int):返回给定索引的名称。 枚举。Index(name string):返回给定索引的名称。 枚举. last():返回最后一个枚举的索引和名称 添加枚举定义。
下面是一些代码:
type EnumItem struct {
index int
name string
}
type Enum struct {
items []EnumItem
}
func (enum Enum) Name(findIndex int) string {
for _, item := range enum.items {
if item.index == findIndex {
return item.name
}
}
return "ID not found"
}
func (enum Enum) Index(findName string) int {
for idx, item := range enum.items {
if findName == item.name {
return idx
}
}
return -1
}
func (enum Enum) Last() (int, string) {
n := len(enum.items)
return n - 1, enum.items[n-1].name
}
var AgentTypes = Enum{[]EnumItem{{0, "StaffMember"}, {1, "Organization"}, {1, "Automated"}}}
var AccountTypes = Enum{[]EnumItem{{0, "Basic"}, {1, "Advanced"}}}
var FlagTypes = Enum{[]EnumItem{{0, "Custom"}, {1, "System"}}}
重构https://stackoverflow.com/a/17989915/863651,使其更具可读性:
package SampleEnum
type EFoo int
const (
A EFoo = iota
C
T
G
)
type IEFoo interface {
Get() EFoo
}
func(e EFoo) Get() EFoo { // every EFoo must fulfill the IEFoo interface
return e
}
func(e EFoo) otherMethod() { // "private"
//some logic
}
我找到了一个更简单的方法。
const (
Stake TX = iota
Withdraw)
type TX int
func (t TX) String() string {
return [...]string{"STAKE", "WITHDRAW"}[t]}
log.Println(Stake.String()) --> STAKE
有一种方法是使用struct命名空间。
这样做的好处是所有枚举变量都在特定的名称空间下,以避免污染。 问题是我们只能用var而不能用const
type OrderStatusType string
var OrderStatus = struct {
APPROVED OrderStatusType
APPROVAL_PENDING OrderStatusType
REJECTED OrderStatusType
REVISION_PENDING OrderStatusType
}{
APPROVED: "approved",
APPROVAL_PENDING: "approval pending",
REJECTED: "rejected",
REVISION_PENDING: "revision pending",
}
此外,这是在一个字节的一个位置存储不同角色的一种非常有效的方法,其中第一个值被设置为1,位移动了一个iota。
package main
import "fmt"
const (
isCaptain = 1 << iota
isTrooper
isMedic
canFlyMars
canFlyJupiter
canFlyMoon
)
func main() {
var roles byte = isCaptain | isMedic | canFlyJupiter
//Prints a binary representation.
fmt.Printf("%b\n", roles)
fmt.Printf("%b\n", isCaptain)
fmt.Printf("%b\n", isTrooper)
fmt.Printf("%b\n", isMedic)
fmt.Printf("Is Captain? %v\n", isCaptain&roles == isCaptain)
fmt.Printf("Is Trooper? %v", isTrooper&roles == isTrooper)
}