Go中的状态表示

2fjabf4q  于 9个月前  发布在  Go
关注(0)|答案(1)|浏览(83)

我们通常使用枚举来表示状态。
例如,在python中:we do

class QueueState(Enum):
    Enqueued = 1
    Processing = 2
    Processed = 3
    Dequeued = 4

字符串
我们可以使用QueueState.Enqueued等来访问它们。在其他语言中也存在同样的行为,比如Java、C#等。我的意思是这些状态有点绑定在QueueState中。
但是当在go中声明状态时,我们使用const和iota,例如:

type QueueState int

const (
    Enqueued QueueState = iota
    Processing
    Processed
    Dequeued
)


我看到这些状态(Enqueued,Processing等)与类型QueueState没有绑定。
要访问它们,我只需要将它们用作常量变量。
例如:

fmt.Println(Enqueued) // prints 0


有没有一种方法可以将这些状态绑定到一个类型中,并像在其他编程语言中一样将它们视为枚举?例如:我想像这样使用它们QueueState.Enqueued

cngwdvgl

cngwdvgl1#

我看到这些状态(Enqueued,Processing等)与类型QueueState没有绑定。
这并不完全正确。当你打印它的值时,你会看到0被打印出来,因为这是它的 * 数值 *。类型QueueState的 * 底层类型 * 是int。但是Enqueued的类型是QueueState(在Go Playground上尝试):

fmt.Printf("%T", Enqueued) // main.QueueState

字符串
如果你想“视觉上”将其绑定到QueueState类型,请将其包含在名称中:

type QueueState int

const (
    QueueStateEnqueued QueueState = iota
    QueueStateProcessing
    QueueStateProcessed
    QueueStateDequeued
)


当它被引用时:QueueStateEnqueued就变得很明显了。这种命名“技巧”在标准库中被广泛使用,一些例子来自net/http包:

const (
        MethodGet     = "GET"
        MethodHead    = "HEAD"
        MethodPost    = "POST"
        ...
)

const (
        StatusContinue           = 100 // RFC 7231, 6.2.1
        StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
        StatusProcessing         = 102 // RFC 2518, 10.1

        StatusOK                   = 200 // RFC 7231, 6.3.1
        StatusCreated              = 201 // RFC 7231, 6.3.2
        ...
)


如果你想要人类可读的打印值,为它定义一个String() string方法:

type QueueState int

func (s QueueState) String() string {
    switch s {
    case QueueStateEnqueued:
        return "Enqueued"
    case QueueStateProcessing:
        return "Processing"
    case QueueStateProcessed:
        return "Processed"
    case QueueStateDequeued:
        return "Dequeued"
    }
    return ""
}


然后打印时(在Go Playground上尝试):

fmt.Println(QueueStateEnqueued) // prints Enqueued


是的,提供这个String()方法并保持它的更新并不是很方便,这就是为什么像stringer这样的工具存在的原因。它们生成这个String()方法的方式比上面的示例实现更紧凑和有效。
还有一个选项可以使用string作为枚举的底层类型,枚举值将作为没有String()方法的字符串表示(在Go Playground上尝试):

type QueueState string

const (
    QueueStateEnqueued   QueueState = "Enqueued"
    QueueStateProcessing QueueState = "Processing"
    QueueStateProcessed  QueueState = "Processed"
    QueueStateDequeued   QueueState = "Dequeued"
)

func main() {
    fmt.Println(QueueStateEnqueued) // prints Enqueued
}


还要注意的是,当其他人引用你的枚举值时,他们使用的是包名。所以你可以将枚举常量放在他们指定的包中,例如,称为queuestate,然后你可以将常量命名为EnqueuedProcessing等,但是当他们被引用时,它将以queuestate.Enqueuedqueuestate.Processing等的形式出现。
还要注意,仅使用常量不能限制类型的值。有关详细信息,请参阅创建常量类型和限制类型的值。

相关问题