在Go中通过Protocol Buffers v3在oneOf字段中使用结构体

huangapple go评论156阅读模式
英文:

Using structs in oneOf field in Protocol Buffers v3 via Go

问题

尝试将 Protocol Buffers v3 和 Go 结合使用(对两者都不熟悉)。

example.proto

syntax = "proto3";

package test;

import "google/protobuf/timestamp.proto";

message Metadata {
    uint64 userID = 2;
    google.protobuf.Timestamp time= 3; 
}

// 当用户退出 Glory 时进行签退
message SignOff {
    Metadata metadata =1;
}

// 当用户登录 Glory 时进行签到
message SignOn {
    Metadata metadata =1;
}

message EventWrapper {
    oneof event {
        SignOff signOff = 1;
        SignOn signOn = 2;
    }
}

使用 protoc 进行转换并在 Go 中使用:

now, _ := ptypes.TimestampProto(time.Now())
event := &pb_test.EventWrapper{
    Event: &pb_test.EventWrapper_SignOn{
        SignOn: &pb_test.SignOn{
            Metadata: &pb_test.Metadata{
                UserID: 1234,
                Time:   now,
            },
        },
    },
}
protoBytes, err := proto.Marshal(event)
if err != nil {
    log.Fatal(err)
}
log.Println(len(protoBytes) == 0)

jsonBytes, _ = json.MarshalIndent(event, "", "\t")
log.Println(string(jsonBytes))

输出显示 JSON 是正确的,但 Protobuf 编码的字节数组为空。

{
    "Event": {
        "SignOn": {
            "metadata": {
                "userID": 1234,
                "time": {
                    "seconds": 1491143507,
                    "nanos": 654053400
                }
            }
        }
    }
}

意图是通过 gRPC 在网络上传输这些对象的数组(repeated *EventWrapper),但目前单个对象无法正常工作。Protobuf 的语言指南没有提到不允许使用结构体。我是否遗漏了什么?

英文:

So trying to using Protocol Buffers v3 and Go together (new to both).

example.proto

syntax = "proto3";

package test;

import "google/protobuf/timestamp.proto";

message Metadata {
    uint64 userID = 2;
    google.protobuf.Timestamp time= 3; 
}

//SignOff when user logs out of Glory
message SignOff {
	Metadata metadata =1;
}

//SignOn when user logs into Glory
message SignOn {
    Metadata metadata =1;
}

message EventWrapper {
    oneof event {
        SignOff signOff = 1;
        SignOn signOn = 2;
    }
}

Converting with protoc and using in Go

now, _ := ptypes.TimestampProto(time.Now())
event := &pb_test.EventWrapper{
	Event: &pb_test.EventWrapper_SignOn{
		SignOn: &pb_test.SignOn{
			Metadata: &pb_test.Metadata{
				UserID: 1234,
				Time:   now,
			},
		},
	},
}
protoBytes, err := proto.Marshal(event)
if err != nil {
	log.Fatal(err)
}
log.Println(len(protoBytes) == 0)

jsonBytes, _ = json.MarshalIndent(event, "", "\t")
log.Println(string(jsonBytes))

The output shows the JSON is right but the protobuf encoded byte array is empty.

{
	"Event": {
		"SignOn": {
			"metadata": {
				"userID": 1234,
				"time": {
					"seconds": 1491143507,
					"nanos": 654053400
				}
			}
		}
	}
}

The intent is the have a array of these (repeated *EventWrapper) to send along the wire via gRPC, but the individual ones don't work at the moment. The protobuf Language Guide doesn't say anything about structs not being allowed. Is there something I'm missing?

答案1

得分: 2

协议缓冲区文档中没有说明oneof不能是结构体,实际上,示例union字段生成了结构体。

我建议使用gogo,我个人在之前的商业项目中使用过。具体来说,使用protoc-gen-gogoslick

请参考这个部分来安装必要的包,然后对你的项目运行以下命令:

protoc --gogoslick_out=Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types:. example.proto
英文:

Nothing in the Protocol Buffer documentation indicates oneof cannot be structs, and in fact the example generates structs for a union field.

I recommend using gogo, which I have personally used for previous commercial projects. Specifically, use protoc-gen-gogoslick

See this section for installing the necessary packages, then run the following for your project

protoc --gogoslick_out=Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types:. example.proto

huangapple
  • 本文由 发表于 2017年4月2日 22:43:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/43169640.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定