在 Go 中表示状态

问题描述 投票:0回答:2

我们一般使用枚举来表示状态。

例如,在Python中:我们做

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
)

我发现这些状态(已排队、正在处理等)与类型

QueueState
没有绑定。

要访问它们,我只需将它们用作常量变量即可。

例如:

fmt.Println(Enqueued) // prints 0

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

QueueState.Enqueued

go enums
2个回答
4
投票

我发现这些状态(已排队、正在处理等)与类型

QueueState
没有绑定。

这并不完全正确。当您打印它的值时,您会看到打印了

0
,因为这是它的 numeric 值。类型
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
,然后你可以将常量命名为
Enqueued
Processing
等,但当引用它们时,它将采用
queuestate.Enqueued
queuestate.Processing
等形式。

另请注意,仅使用常量无法限制类型的值。有关详细信息,请参阅创建常量类型并限制类型的值


0
投票

看这个

import "github.com/lvyahui8/goenum"

// define enum type
type State struct {
    goenum.Enum
}

// define enum
var (
    Created = goenum.NewEnum[State]("Created")
    Running = goenum.NewEnum[State]("Running")
    Success = goenum.NewEnum[State]("Success")
)

// Usage
Created.Name() // string "Created"
Created.Ordinal() // int 0
goenum.ValueOf[State]("Created") // struct instance: Created
Created.Equals(*goenum.ValueOf[State]("Created")) // true
goenum.Values[State]() // equals []State{Created,Running,Success}

需要

  • Go版本>=1.18

这是java枚举类的实现参考,希望对你有帮助。

查看更多:https://github.com/lvyahui8/goenum/tree/main?tab=readme-ov-file

© www.soinside.com 2019 - 2024. All rights reserved.