Protocol buffer
protocol buffer 是一种数据传输协议,比 Json、xml 等效率更高。
准确的说 pb 是传输协议,而后两者是序列化协议。
序列化协议有两个属性:
- 结构化程度(人类可读性)
- 压缩程度(序列化后的数据大小)
同一个对象序列化后,以上两个属性基本上是此消彼长、不可兼得的。因为要想人类可读就必须是字符串,且需要加入如{}[],以及换行符等符号做辅助,必然数据不能很好地压缩。
因此,pb 相对于 Json、XML 结构化很差,但是压缩程度很高,所以传输效率高。只不过人类程序员不需要去阅读序列化后的数据文本,其定义了.proto文件后直接生成客户端、服务端代码,程序员在两端都只需要关心程序中的对象(序列化前的对象和已反序列化后的对象)。
关于变量的处理
protocol buffer 本身是有时间戳的支持的,与 golang 可以融洽地结合。
实际大部分编程对时间的处理只需要精确到秒,也可以简略一点,直接使用 int32 或 int64 传输时间戳。
Timestamp
在 .proto文件中使用google.protobuf.Timestamp
类型定义时间:
syntax = "proto3";
package pb;
import public "google/protobuf/timestamp.proto";
message person{
google.protobuf.Timestamp birthday = 1;
}
对应生成的 .pb.go 文件中类型为*timestamp.Timestamp
:
type Person struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Birthday *timestamp.Timestamp `protobuf:"bytes,1,opt,name=birthday,proto3" json:"birthday,omitempty"`
}
其中,timestamp.Timestamp
的 message 类型定义如下
message Timestamp {
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
int64 seconds = 1;
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
int32 nanos = 2;
}
go 语言 time.Time
类型与 timestamp.Timestamp
互相转换使用github.com/golang/protobuf/ptypes
包下方法:
package pb
import (
"fmt"
"github.com/golang/protobuf/ptypes"
"time"
)
func TimeStampFeature() {
//Timestamp 转 Time
//获取的是系统时区的时间戳
pbTimestamp := ptypes.TimestampNow()
//此方法默认 UTC 时区
goTime, _ := ptypes.Timestamp(pbTimestamp)
//设定为系统时区
fmt.Println(goTime.Local())
//Time 转 Timestamp
goTime2 := time.Now()
pbTimestamp2, _ := ptypes.TimestampProto(goTime2)
fmt.Println(pbTimestamp2)
}
输出为:
=== RUN TestTimeStampFeature
2020-10-26 14:10:48.69129 +0800 CST
seconds:1603692648 nanos:691445000
--- PASS: TestTimeStampFeature (0.00s)
PASS
秒级时间戳
若只时间处理只精确到秒,则不必使用 time.Time
和timestamp.Timestamp
来处理和传输时间戳,直接使用 int32
或 int64
来表示秒级时间戳,免去类型互相转换。