有没有办法提取 protobuf oneof int 值?
Is there a way to extract a protobuf oneof int value?
TL;DR: 在 Go 中,有没有办法获取 protobuf oneof case 的整数值?
详情:
在 C# 中,我可以使用类似以下内容轻松查询 Oneof 案例的整数值:
opcode = (int)ChannelMessage.ChannelActionOneofCase.Register; // opcode will equal 1
但是在 Golang 中,似乎没有任何东西可以用来轻松提取整数值。
我知道我可以打开类型本身:
switch m.ChannelAction.(type) {
case *proto.ChannelMessage_Register:
...
然而,在我的情况下,这将要求我解组每条消息,这对于某些类型来说并不是绝对必要的,因为我每次都需要发送操作码。
如果有帮助,我的 ChannelMessage 类型如下所示:
message ChannelMessage
{
oneof ChannelAction
{
ChannelRegister register = 1;
ChannelUnregister unregister = 2;
...
}
}
你是对的,你可以通过类型切换来做到这一点:
// my example used simple strings instead of custom messages.
example := proto.ChannelMessage{
ChannelAction: &pbExample.ChannelMessage_Register{"foobar"},
}
t := example.GetChannelAction()
switch v := t.(type) {
case *pbExample.ChannelMessage_Register:
fmt.Printf("register\n")
case *pbExample.ChannelMessage_Unregister:
fmt.Printf("unregister\n")
default:
fmt.Printf("I don't know about type %T!\n", v)
}
// what you also can do is to ask directly your oneOf case and try to typecast it.
val, ok := example.GetRegister().(int) // GetUnregister is other option.
if ok {
// black magic happens here
}
这 可能 不是您实际想要做的,但是 google.golang.org/protobuf/reflect/protoreflect package does have the necessary functions, if you need to refer to the field numbers 属于您 oneof
的字段的一部分。
例如,假设您已将原型导入为 pb
,要按名称获取数字 1(如在您的 C# 示例中),您可以执行以下操作:
desc := (&pb.ChannelMessage{}).ProtoReflect().Descriptor()
opcode := desc.Fields().ByName("register").Number()
(这并非严格特定于 oneof
,因为 oneof
字段实际上只是常规消息字段,带有附加约束,只能设置其中一个。)
或者在消息 m
中找出 oneof
字段设置为哪个字段编号而不写出类型开关,假设您知道其中一个肯定已设置,您可以这样做:
ref := m.ProtoReflect()
desc := ref.Descriptor()
num := ref.WhichOneof(desc.Oneofs().ByName("ChannelAction")).Number()
在这两种情况下,结果 (opcode
、num
) 都将是具有基础类型 int32
的数字类型 (protoreflect.FieldNumber = protowire.Number),您可以将其转换到.
TL;DR: 在 Go 中,有没有办法获取 protobuf oneof case 的整数值?
详情:
在 C# 中,我可以使用类似以下内容轻松查询 Oneof 案例的整数值:
opcode = (int)ChannelMessage.ChannelActionOneofCase.Register; // opcode will equal 1
但是在 Golang 中,似乎没有任何东西可以用来轻松提取整数值。
我知道我可以打开类型本身:
switch m.ChannelAction.(type) {
case *proto.ChannelMessage_Register:
...
然而,在我的情况下,这将要求我解组每条消息,这对于某些类型来说并不是绝对必要的,因为我每次都需要发送操作码。
如果有帮助,我的 ChannelMessage 类型如下所示:
message ChannelMessage
{
oneof ChannelAction
{
ChannelRegister register = 1;
ChannelUnregister unregister = 2;
...
}
}
你是对的,你可以通过类型切换来做到这一点:
// my example used simple strings instead of custom messages.
example := proto.ChannelMessage{
ChannelAction: &pbExample.ChannelMessage_Register{"foobar"},
}
t := example.GetChannelAction()
switch v := t.(type) {
case *pbExample.ChannelMessage_Register:
fmt.Printf("register\n")
case *pbExample.ChannelMessage_Unregister:
fmt.Printf("unregister\n")
default:
fmt.Printf("I don't know about type %T!\n", v)
}
// what you also can do is to ask directly your oneOf case and try to typecast it.
val, ok := example.GetRegister().(int) // GetUnregister is other option.
if ok {
// black magic happens here
}
这 可能 不是您实际想要做的,但是 google.golang.org/protobuf/reflect/protoreflect package does have the necessary functions, if you need to refer to the field numbers 属于您 oneof
的字段的一部分。
例如,假设您已将原型导入为 pb
,要按名称获取数字 1(如在您的 C# 示例中),您可以执行以下操作:
desc := (&pb.ChannelMessage{}).ProtoReflect().Descriptor()
opcode := desc.Fields().ByName("register").Number()
(这并非严格特定于 oneof
,因为 oneof
字段实际上只是常规消息字段,带有附加约束,只能设置其中一个。)
或者在消息 m
中找出 oneof
字段设置为哪个字段编号而不写出类型开关,假设您知道其中一个肯定已设置,您可以这样做:
ref := m.ProtoReflect()
desc := ref.Descriptor()
num := ref.WhichOneof(desc.Oneofs().ByName("ChannelAction")).Number()
在这两种情况下,结果 (opcode
、num
) 都将是具有基础类型 int32
的数字类型 (protoreflect.FieldNumber = protowire.Number),您可以将其转换到.