Go:如何使用枚举作为类型?
Go: How to use enum as a type?
我有一个定义特定事件的事件列表(枚举):
package events
const (
NEW_USER = "NEW_USER"
DIRECT_MESSAGE = "DIRECT_MESSAGE"
DISCONNECT = "DISCONNECT"
)
并且有一个结构将使用此枚举作为其属性之一
type ConnectionPayload struct {
EventName string `json:"eventName"`
EventPayload interface{} `json:"eventPayload"`
}
有没有一种方法可以使用 enum
作为 EventName 的类型而不是字符串?
这在 typescript
中是可能的,但不确定如何在 golang 中做到这一点。
我希望开发人员使用枚举强制使用正确的事件名称,而不是通过使用任何随机字符串作为事件名称来犯错误。
您可以通过生成如下代码来实现。
type EventNames string
const (
NEW_USER EventNames = "NEW_USER"
DIRECT_MESSAGE EventNames = "DIRECT_MESSAGE"
DISCONNECT EventNames = "DISCONNECT"
)
然后将您的结构更改为:
type ConnectionPayload struct {
EventName EventNames `json:"eventName"`
EventPayload interface{} `json:"eventPayload"`
}
试试这个:
package main
import (
"fmt"
"gopkg.in/go-playground/validator.v9"
)
type EventName string
const (
NEW_USER EventName = "NEW_USER"
DIRECT_MESSAGE EventName = "DIRECT_MESSAGE"
DISCONNECT EventName = "DISCONNECT"
)
type ConnectionPayload struct {
EventName EventName `json:"eventName" validate:"oneof=NEW_USER DIRECT_MESSAGE DISCONNECT"`
EventPayload interface{} `json:"eventPayload"`
}
func (s *ConnectionPayload) Validate() error {
validate := validator.New()
return validate.Struct(s)
}
func main() {
a := ConnectionPayload{
EventName: "NEW_USER",
}
b := ConnectionPayload{
EventName: "NEW_USERR",
}
err := a.Validate()
fmt.Println(a, err)
err = b.Validate()
fmt.Println(b, err)
}
go 中目前没有枚举类型,目前也没有直接的方法来执行与 typescript 相同的规则。
go 中的一个常见做法是使用 发布的建议:
定义自定义类型,并使用您的“枚举”值键入常量:
type EventName string
const (
NEW_USER EventName = "NEW_USER"
DIRECT_MESSAGE EventName = "DIRECT_MESSAGE"
DISCONNECT EventName = "DISCONNECT"
)
这允许您在您的 go 代码中标记您期望这样一个值的地方:
// example function signature :
func OnEvent(e EventName, id int) error { ... }
// example struct :
type ConnectionPayload struct {
EventName EventName `json:"eventName"`
EventPayload interface{} `json:"eventPayload"`
}
它会阻止将普通的 string
分配给 EventName
var str string = "foo"
var ev EventName
ev = str // won't compile
OnEvent(str, 42) // won't compile
已知的限制是:
- 在 go 中,总是有一个零值:
var ev EventName // ev is ""
- 字符串文字与类型化变量不同,可以赋值:
var ev EventName = "SOMETHING_ELSE"
- 允许转换:
var str string = "foo"
var ev EventName = EventName(str)
- 没有检查解组:
jsn := []byte(`{"eventName":"SOMETHING_ELSE","eventPayload":"some message"}`)
err := json.Unmarshal(jsn, &payload) // no error
https://go.dev/play/p/vMUTpvH8DBb
如果您想要进行更严格的检查,则必须自己编写验证器或自定义解组器。
我有一个定义特定事件的事件列表(枚举):
package events
const (
NEW_USER = "NEW_USER"
DIRECT_MESSAGE = "DIRECT_MESSAGE"
DISCONNECT = "DISCONNECT"
)
并且有一个结构将使用此枚举作为其属性之一
type ConnectionPayload struct {
EventName string `json:"eventName"`
EventPayload interface{} `json:"eventPayload"`
}
有没有一种方法可以使用 enum
作为 EventName 的类型而不是字符串?
这在 typescript
中是可能的,但不确定如何在 golang 中做到这一点。
我希望开发人员使用枚举强制使用正确的事件名称,而不是通过使用任何随机字符串作为事件名称来犯错误。
您可以通过生成如下代码来实现。
type EventNames string
const (
NEW_USER EventNames = "NEW_USER"
DIRECT_MESSAGE EventNames = "DIRECT_MESSAGE"
DISCONNECT EventNames = "DISCONNECT"
)
然后将您的结构更改为:
type ConnectionPayload struct {
EventName EventNames `json:"eventName"`
EventPayload interface{} `json:"eventPayload"`
}
试试这个:
package main
import (
"fmt"
"gopkg.in/go-playground/validator.v9"
)
type EventName string
const (
NEW_USER EventName = "NEW_USER"
DIRECT_MESSAGE EventName = "DIRECT_MESSAGE"
DISCONNECT EventName = "DISCONNECT"
)
type ConnectionPayload struct {
EventName EventName `json:"eventName" validate:"oneof=NEW_USER DIRECT_MESSAGE DISCONNECT"`
EventPayload interface{} `json:"eventPayload"`
}
func (s *ConnectionPayload) Validate() error {
validate := validator.New()
return validate.Struct(s)
}
func main() {
a := ConnectionPayload{
EventName: "NEW_USER",
}
b := ConnectionPayload{
EventName: "NEW_USERR",
}
err := a.Validate()
fmt.Println(a, err)
err = b.Validate()
fmt.Println(b, err)
}
go 中目前没有枚举类型,目前也没有直接的方法来执行与 typescript 相同的规则。
go 中的一个常见做法是使用
定义自定义类型,并使用您的“枚举”值键入常量:
type EventName string
const (
NEW_USER EventName = "NEW_USER"
DIRECT_MESSAGE EventName = "DIRECT_MESSAGE"
DISCONNECT EventName = "DISCONNECT"
)
这允许您在您的 go 代码中标记您期望这样一个值的地方:
// example function signature :
func OnEvent(e EventName, id int) error { ... }
// example struct :
type ConnectionPayload struct {
EventName EventName `json:"eventName"`
EventPayload interface{} `json:"eventPayload"`
}
它会阻止将普通的 string
分配给 EventName
var str string = "foo"
var ev EventName
ev = str // won't compile
OnEvent(str, 42) // won't compile
已知的限制是:
- 在 go 中,总是有一个零值:
var ev EventName // ev is ""
- 字符串文字与类型化变量不同,可以赋值:
var ev EventName = "SOMETHING_ELSE"
- 允许转换:
var str string = "foo" var ev EventName = EventName(str)
- 没有检查解组:
jsn := []byte(`{"eventName":"SOMETHING_ELSE","eventPayload":"some message"}`) err := json.Unmarshal(jsn, &payload) // no error
https://go.dev/play/p/vMUTpvH8DBb
如果您想要进行更严格的检查,则必须自己编写验证器或自定义解组器。