

























安装 protoc
brew install protobuf
为 protoc 安装 go 插件
$ go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest \
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
这些插件不能在同一条命令里执行安装,因为同一条 go install 命令安装的插件,必须是在同一个 module 下的,某则会有错误提示: All packages must be provided by the same module.
参考文档: Encoding
| Type | Meaning | Used For |
|---|---|---|
| 0 | Varint | int32, int64, uint32, uint64, sint32, sint64, bool, enum |
| 1 | 64-bit | fixed64, sfixed64, double |
| 2 | Length-delimited | string, bytes, embedded messages, packed repeated fields |
| 3 | Start group | groups (deprecated) |
| 4 | End group | groups (deprecated) |
| 5 | 32-bit | fixed32, sfixed32, float |
syntax = "proto3";
message StringMessage {
string value = 1;
int32 count = 2;
int64 num = 3;
string home = 4;
}
message StringMessage2 { string val = 1; }
使用 protoc 将 protofile.proto 转换成 golang 结构protoc \
--go_out=./gen/ \
--go_opt paths=source_relative \
protofile.proto
生成 protofile.pb.go 如下:type StringMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
Count int32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"`
Num int64 `protobuf:"varint,3,opt,name=num,proto3" json:"num,omitempty"`
Home string `protobuf:"bytes,4,opt,name=home,proto3" json:"home,omitempty"`
}
type StringMessage2 struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Val string `protobuf:"bytes,1,opt,name=val,proto3" json:"val,omitempty"`
}
package main
import (
"fmt"
pb "path_to_generated_pb_go"
"google.golang.org/protobuf/proto"
)
func main() {
msg := &pb.StringMessage{Value: "abc", Count: 127, Num: 128, Home: "China"}
fmt.Println("msg:")
fmt.Println(msg)
out, _ := proto.Marshal(msg)
fmt.Println(out)
msg2 := &pb.StringMessage2{}
proto.Unmarshal(out, msg2)
fmt.Println("\nmsg2:")
fmt.Println(msg2)
out2, _ := proto.Marshal(msg2)
fmt.Println(out2)
}
msg:
value:"abc" count:127 num:128 home:"China"
[10 3 97 98 99 16 127 24 128 1 34 5 67 104 105 110 97]
msg2:
val:"abc" 2:127 3:128 4:"China"
[10 3 97 98 99 16 127 24 128 1 34 5 67 104 105 110 97]
[10 3 97 98 99] 这一段
10 由 StringMessage.Value 的 fieldNumber 1 和 wireType 2 (string) 构成:(1<<3|2) = 103 表示接下来3个字节构成字符串97 98 99 是 abc 的 ASCII 编码[16 127] 这一段
16 由 StringMessage.Count 的 fieldNumber 2 和 wireType 0 (int32) 构成:(2<<3|0) = 16127 用一个字节足以表示127[24 128 1] 这一段
24 由 StringMessage.Num 的 filedNumber 3 和 wireType 0 (int64) 构成:(3<<3|0) = 24128 1 二进制为 1000 0000 0000 0001,根据 protobuf 的规则,首个 1 表示后续字节依然要跟本字节一起表示数字;第二个字节的首个 bit 为 0,表明后续自己跟本字段无关。且 protobuf 将数字按照 bigEndian 存储,所以解码后的数字为 000 0001 000 0000,值为 128[34 5 67 104 105 110 97] 这一段
34 由 StringMessage.Home 的 fileNumber 4 和 wireType 2 (string) 构成:(4<<3|2) = 345 表示接下来5个字节构成字符串67 104 105 110 97 是 China 的 ASCII 编码2, 3, 4 的字段,但是 StringMessage2 的实例 msg2 中依然可以在其中保留相关字段的内容。看一下 protobuf 根据 .proto 生成的 StringMessage2 的定义:type StringMessage2 struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Val string `protobuf:"bytes,1,opt,name=val,proto3" json:"val,omitempty"`
}
这些未在 StringMessage2 中定义的内容,就保存在 unknownFields 字段里,重新序列化后,可以得到跟原始内容相同的序列化结果。posted on 2022-07-10 20:05 HorseShoe2016 阅读(324) 评论() 收藏 举报
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。