背景
protobuf 2中定义的enum枚举值必须为数字类型,故不支持string类型,但有些业务场景又确实需要定义string常量。
目标
在protobuf 2中定义string常量。
方案
思路:通optional + default实现string常量。
细节:
1、protobuf定义
syntax = "proto2";
package stonelu.learn.pb;
message Constant {
message TestStringConst {
optional string NO_TEST_STRING_CONST = 1 [default = "no_test_string_const"]; // val: no_test_string_const
optional string Email = 2 [default = "email"]; // val: email
optional string Sex = 3 [default = "sex"]; // val: sex
optional string Address = 4 [default = "address"]; // val address
}
}
2、生成pb.go文件(文件名后缀由生成语言决定,此处以go为例)
指令不在此赘述。
生成的文件关键信息如下(注意中文注释部分):
type Constant_TestStringConst struct {
NO_TEST_STRING_CONST *string `protobuf:"bytes,1,opt,name=NO_TEST_STRING_CONST,json=NOTESTSTRINGCONST,def=no_test_string_const" json:"NO_TEST_STRING_CONST"`
Email *string `protobuf:"bytes,2,opt,name=Email,def=email" json:"Email"`
Sex *string `protobuf:"bytes,3,opt,name=Sex,def=sex" json:"Sex"`
Address *string `protobuf:"bytes,4,opt,name=Address,def=address" json:"Address"`
XXX_unrecognized []byte `json:"-"`
}
func (m *Constant_TestStringConst) Reset() { *m = Constant_TestStringConst{} }
func (m *Constant_TestStringConst) String() string { return proto.CompactTextString(m) }
func (*Constant_TestStringConst) ProtoMessage() {}
func (*Constant_TestStringConst) Descriptor() ([]byte, []int) {
return fileDescriptorSellerCsRouting, []int{0, 2}
}
const Default_Constant_TestStringConst_NO_TEST_STRING_CONST string = "no_test_string_const"
const Default_Constant_TestStringConst_Email string = "email"
const Default_Constant_TestStringConst_Sex string = "sex"
const Default_Constant_TestStringConst_Address string = "address"
func (m *Constant_TestStringConst) GetNO_TEST_STRING_CONST() string {
if m != nil && m.NO_TEST_STRING_CONST != nil {
return *m.NO_TEST_STRING_CONST
}
return Default_Constant_TestStringConst_NO_TEST_STRING_CONST
}
func (m *Constant_TestStringConst) GetEmail() string {
// 【核心代码】
// 如果email字段有值,则返回,但其实一般不会对其做赋值
if m != nil && m.Email != nil {
return *m.Email
}
// 一般都走下面这里:返回默认值:"email"
// sex、address字段类同,后面不再赘述
return Default_Constant_TestStringConst_Email
}
func (m *Constant_TestStringConst) GetSex() string {
if m != nil && m.Sex != nil {
return *m.Sex
}
return Default_Constant_TestStringConst_Sex
}
func (m *Constant_TestStringConst) GetAddress() string {
if m != nil && m.Address != nil {
return *m.Address
}
return Default_Constant_TestStringConst_Address
}
3、使用
v := (&stonelu_learn_pb.Constant_TestStringConst{}).GetEmail()
t.Logf("v: %v", v)