我正在尝试在golang中使用protobuf2枚举,但我无法弄清楚。
我创建了一个简单的protobuf文件:
1 2 3 4 5 6 7 8 | syntax = "proto2" ; package enum ; message Foo{ enum Bar{ LOL = 1; } optional Bar baz = 1; } |
然后我创建了一个简单的golang文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 | package main import ( enum"./enum" "github.com/golang/protobuf/proto" ) func main() { msg := &enum.Foo{ Baz: enum.Foo_LOL, } proto.Marshal(&msg) } |
我遇到错误。
1 | ./foo.go:10: cannot use enum.Foo_LOL (type enum.Foo_Bar) as type *enum.Foo_Bar in field value |
解决起来似乎很简单,只需在
1 2 3 4 5 6 7 8 9 10 11 12 13 | package main import ( enum"./enum" "github.com/golang/protobuf/proto" ) func main() { msg := &enum.Foo{ Baz: &enum.Foo_LOL, } proto.Marshal(&msg) } |
否:
1 | ./foo.go:10: cannot take the address of enum.Foo_LOL |
我搜索了google,发现这个家伙正在被漫游器诱骗。他有一些有效的代码,但是它很冗长,足以让一位圣经学者感到厌倦:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package main import ( enum"./enum" "github.com/golang/protobuf/proto" ) var lolVar = enum.Foo_LOL func main() { msg := &enum.Foo{ Baz: &lolVar, } proto.Marshal(msg) } |
我查看了生成的代码,发现了一个
1 2 3 4 5 6 7 8 9 10 11 12 13 | package main import ( enum"./enum" "github.com/golang/protobuf/proto" ) func main() { msg := &enum.Foo{ Baz: enum.Foo_LOL.Enum(), } proto.Marshal(msg) } |
预期的方法是什么?
具有
Protobuf生成具有指针类型的枚举字段,因此
此外,您在protobuf文件中列出的枚举值将在Go中生成为常量。而且您不能获取常量值的地址,有关详细信息,请参见:在go
中查找常量的地址
如果您的protobuf生成了一个
如果丢失,最简单的方法是创建一个(本地)变量,您可以使用其地址:
1 2 3 4 5 | lol := enum.Foo_LOL msg := &enum.Foo{ Baz: &lol, } err := proto.Marshal(msg) |
如果必须多次/多次执行此操作,请创建一个辅助函数,该函数可以满足
1 | func barPtr(b enum.Foo_Bar) *enum.Foo_Bar { return &b } |
并使用它:
1 2 3 4 | msg := &enum.Foo{ Baz: barPtr(enum.Foo_LOL), } err := proto.Marshal(msg) |
还有许多其他选项可以获取指向整数类型的指针,但是它们不一定更干净或更有效。您可以在此处看到不同方法的列表:如何在Go中执行文字* int64?
- 什么时候以及为什么不创建Enum方法?
-
@timthelion我不确定,但是我也使用protobuf,并且没有为我的枚举生成此
Enum() 方法。 - 您是否有机会使用proto3?查看代码,我发现不是为proto3文件创建的Enum方法,可能是因为proto3不支持可选字段。
-
@timthelion是的,刚要发表评论。我已经调查过了。如果使用
syntax="proto2" ,则将字段作为指针生成,并且将Enum() 方法添加到枚举中。当为syntax="proto3" 时,该字段为非指针,并且不会生成任何Enum() 方法。因此,如果您"升级"到"proto3" ,则将"丢失"Enum() 方法。是的,在proto3 中,默认情况下字段为optional 。