本期看点(技巧类用【技】表示,易错点用【易】表示):
- JSON Marshal和Proto Marshal在Protobuf Message结构体上使用的不同【易】
- channel方式代替time.Sleep()方法【技】
正文开始:
JSON Marshal和Proto Marshal在gRPC Message上使用的不同
我们先定义一个Proto Buffer文件,内容为一个Message,有两个属性,其中一个属性为string类型,一个为onef类型:
syntax = "proto3"; option go_package = "/test"; package cmd; message UserInfo { string name = 1; oneof address { string school_addr = 2; string home_addr = 3; } }
接下来我们编译成pb.go文件
protoc -I=. --go_out=.. ./hello.proto
具体编译后的结构体:
type UserInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Types that are assignable to Address: // *UserInfo_SchoolAddr // *UserInfo_HomeAddr Address isUserInfo_Address `protobuf_oneof:"address"` } // ... type UserInfo_SchoolAddr struct { SchoolAddr string `protobuf:"bytes,2,opt,name=school_addr,json=schoolAddr,proto3,oneof"` } // ... type UserInfo_HomeAddr struct { HomeAddr string `protobuf:"bytes,3,opt,name=home_addr,json=homeAddr,proto3,oneof"` }
然后我们写两个测试方法:
方法一:JSON Marshl的方式序列化结构体
func TestJSONMarshal(t *testing.T) { u := UserInfo{ Name: "zs", Address: &UserInfo_HomeAddr{HomeAddr: "Beijing"}, } marshal, _ := json.Marshal(u) fmt.Println(string(marshal)) var u2 UserInfo _ = json.Unmarshal(marshal, &u2) fmt.Println(u2) }
结果:
方法二:Proto Marshal的方式序列化结构体
func TestProtoMarshal(t *testing.T) { u := UserInfo{ Name: "zs", Address: &UserInfo_HomeAddr{HomeAddr: "Beijing"}, } marshal, _ := proto.Marshal(u) fmt.Println(string(marshal)) var u2 UserInfo _ = proto.Unmarshal(marshal, u2) fmt.Println(u2) }
结果:
对比上述的结果,我们会发现有些不同:
- 序列化后的内容不同,JSON Marshal序列化后的内容可读性较高但是内容占用空间多
- 反序列化时Proto Marshal的方式能够自动识别oneof类型的属性
因此我们得出结论,在直接序列化Message时最好使用Proto Marshal的方式进行序列化,防止特殊的属性不能够识别,而且该序列化的方式更加节省空间,缺点则是序列化的结果可读性不高。
channel方式代替time.Sleep()方法
最新发现的新操作,直接上代码:
func TestSleep(t *testing.T) { <-time.After(time.Second) // 相当于time.Sleep(time.Second) }
本期到此结束~