我们一般使用枚举来表示状态。
例如,在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
我发现这些状态(已排队、正在处理等)与类型
没有绑定。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
等形式。
另请注意,仅使用常量无法限制类型的值。有关详细信息,请参阅创建常量类型并限制类型的值。
看这个
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}
需要
这是java枚举类的实现参考,希望对你有帮助。
查看更多:https://github.com/lvyahui8/goenum/tree/main?tab=readme-ov-file