我试图表示一个简化的染色体,它由N个碱基组成,每个碱基只能是{a, C, T, G}中的一个。

我想用枚举形式化约束,但我想知道在Go中模拟枚举的最惯用的方式是什么。


当前回答

此外,这是在一个字节的一个位置存储不同角色的一种非常有效的方法,其中第一个值被设置为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)

}

其他回答

从Go 1.4开始,Go生成工具已经与stringer命令一起引入,使枚举易于调试和打印。

有一种方法是使用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",
}

这是在golang中实现enum的安全方法:

package main

import (
    "fmt"
)

const (
    MALE   = _gender(1)
    FEMALE = _gender(2)
    RED    = _color("RED")
    GREEN  = _color("GREEN")
    BLUE   = _color("BLUE")
)

type Gender interface {
    _isGender()
    Value() int
}

type _gender int

func (_gender) _isGender() {}

func (_g _gender) Value() int {
    return int(_g)
}

type Color interface {
    _isColor()
    Value() string
}

type _color string

func (_color) _isColor() {}

func (_c _color) Value() string {
    return string(_c)
}

func main() {
    genders := []Gender{MALE, FEMALE}
    colors := []Color{RED, GREEN, BLUE}
    fmt.Println("Colors =", colors)
    fmt.Println("Genders =", genders)
}

输出:

Colors = [RED GREEN BLUE]
Genders = [1 2]

你可以这样做:

type MessageType int32

const (
    TEXT   MessageType = 0
    BINARY MessageType = 1
)

使用此代码,编译器应该检查枚举类型

参考jnml的答案,您可以通过根本不导出Base类型来防止创建Base类型的新实例(即将其写成小写)。如果需要,您可以创建一个具有返回基类型的方法的可导出接口。这个接口可以用在处理base的外部函数中。

package a

type base int

const (
    A base = iota
    C
    T
    G
)


type Baser interface {
    Base() base
}

// every base must fulfill 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.b eser现在实际上就像一个枚举。 只有在a包中才能定义新实例。