我正在尝试在golang中使用protobuf2枚举,但我无法弄明白。
我创建了一个简单的protobuf文件:
syntax = "proto2" ;
package enum ;
message Foo{
enum Bar{
LOL = 1;
}
optional Bar baz = 1;
}
我创建了一个简单的golang文件:
package main
import (
enum "./enum"
"github.com/golang/protobuf/proto"
)
func main() {
msg := &enum.Foo{
Baz: enum.Foo_LOL,
}
proto.Marshal(&msg)
}
我收到了错误。
./foo.go:10: cannot use enum.Foo_LOL (type enum.Foo_Bar) as type *enum.Foo_Bar in field value
解决问题似乎很简单,只需在&
前添加enum.Foo_Bar
。
package main
import (
enum "./enum"
"github.com/golang/protobuf/proto"
)
func main() {
msg := &enum.Foo{
Baz: &enum.Foo_LOL,
}
proto.Marshal(&msg)
}
都能跟得上:
./foo.go:10: cannot take the address of enum.Foo_LOL
我搜索了谷歌并找到了this guy being trolled by a bot。他有一些工作代码,但是它足够冗长以致于一位圣经学者:
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)
}
我查看了生成的代码并找到了一个Enum
方法,该方法也有效,但是足够冗长以致于税务审计员:
package main
import (
enum "./enum"
"github.com/golang/protobuf/proto"
)
func main() {
msg := &enum.Foo{
Baz: enum.Foo_LOL.Enum(),
}
proto.Marshal(msg)
}
预期的方法是什么?
答案 0 :(得分:1)
带syntax="proto2"
的Protobuf会生成带指针类型的枚举字段,因此Foo.baz
的类型为*Foo_Bar
。您不能为此字段指定非指针Foo_Bar
值,只能指定指针值。
此外,您在protobuf文件中列出的枚举值将生成为Go中的常量。而且您无法获取常量值的地址,详情请参阅:Find address of constant in go
如果你的protobuf生成一个Enum()
方法返回一个指向该值的指针,那么没关系,你可以使用它。但是这种方法并不总是生成,所以如果你没有找到某种类型/枚举,请不要感到惊讶。
如果缺少,最简单的方法是创建一个(本地)变量,并且可以使用其地址:
lol := enum.Foo_LOL
msg := &enum.Foo{
Baz: &lol,
}
err := proto.Marshal(msg)
如果必须多次/多次执行此操作,请创建一个辅助函数,以填充Enum()
方法的用途。这就是你如何创建一个:
func barPtr(b enum.Foo_Bar) *enum.Foo_Bar { return &b }
使用它:
msg := &enum.Foo{
Baz: barPtr(enum.Foo_LOL),
}
err := proto.Marshal(msg)
还有许多其他选项可以获取指向整数类型的指针,但它们不一定更清晰或更有效。您可以在此处查看不同方法的列表:How do I do a literal *int64 in Go?