go - 如何使用 golang 设置 protobuf2 枚举

标签 go enums protocol-buffers

我正在尝试在 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)
}

预期的方法是什么?

最佳答案

使用 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?

关于go - 如何使用 golang 设置 protobuf2 枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50464205/

相关文章:

枚举可以被认为是不安全的吗?

parameters - 如何更改枚举中的参数值(Swift)

java - JComboBox 填充枚举变量值

dictionary - 在 golang 中格式化 map[]

google-app-engine - 仅对我的一个模块有很长的延迟

go - 为什么传递的变量不呈现在html/template中?

c++ - 使用 Protocol Buffer 描述符对象从 .proto 文件中读取注释

java - 如何使用 Jackson Mixin 将 Json 映射到 Proto?

c++ - 使用 MSVC 2015 编译 GRPC 0.15 以在 Windows 上与 Qt 5.6 一起使用

go - 错误 : invalid_request Missing required parameter: client_id in golang