往期回顾:
- Go语言开发小技巧&易错点100例(一)
- Go语言开发小技巧&易错点100例(二)
- Go语言开发小技巧&易错点100例(三)
- Go语言开发小技巧&易错点100例(四)
- Go语言开发小技巧&易错点100例(五)
- Go语言开发小技巧&易错点100例(六)
- Go语言开发小技巧&易错点100例(七)
本期看点(技巧类用【技】表示,易错点用【易】表示):
- 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.MessageStatesizeCache protoimpl.SizeCacheunknownFields protoimpl.UnknownFieldsName string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`// Types that are assignable to Address:// *UserInfo_SchoolAddr// *UserInfo_HomeAddrAddress 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)}
本期到此结束~