使用protobuf3踩過的那些坑(Java)

相對于 protobuf2,protobuf3 變化很大,尤其是默認值的變化給使用者帶來很大不便。

默認值

protobuf3 刪除了 protobuf2 中用來設(shè)置默認值的 default 關(guān)鍵字,取而代之的是protobuf3為各類型定義的默認值,也就是約定的默認值,如下表所示:

類型 默認值
bool false
整型 0
string 空字符串""
枚舉enum 第一個枚舉元素的值,因為Protobuf3強制要求第一個枚舉元素的值必須是0,所以枚舉的默認值就是0;
message 不是null,而是DEFAULT_INSTANCE

可以看出來,protobuf3定義的默認值跟Java中類的屬性的默認值規(guī)則并不一樣:Java中,如果類的屬性類型是類,則該屬性默認值是null,而protobuf3中,string、message的默認值都不是null。

枚舉enum類型:

1、不支持一個proto文件中,多個枚舉中定義相同的枚舉常量名。

如下的兩個枚舉,定義在同一個proto文件中:

enum Enum1 {
    IDLE = 0;
    RUNNING = 1;
}

enum Enum2 {
    IDLE = 5;
    RUNNING = 6;
}

編譯時,會報出錯誤:IDLE is already defined in "xxx",出現(xiàn)這一錯誤的原因就是:Protobuf3中不允許同一proto中,多個枚舉中使用相同的枚舉值。
而有意思的是:在proto編譯生成的Java文件中,protobuf自己卻為每個枚舉都添加了一個UNRECOGNIZED(值為-1),意味著protobuf不允許使用者為兩個枚舉添加相同的枚舉值,卻允許自己添加。。。
實際上,這一現(xiàn)象是有悖于Java開發(fā)者習(xí)慣的,因為在Java中,并不會對枚舉有上述限制,在使用上會讓人感覺很別扭,帶著這個困惑,我提了個bug:
Can not define two same enum name in the same proto file

而官方的解答是:
1、設(shè)計如此,給名字一樣的枚舉值加個前綴來解決這個問題。。。
2、Protobuf要兼顧所有語言的特性,我試了一下:C語言也不不允許這么定義(以前真不知道這個情況,學(xué)藝不精呀。。)。

2、枚舉第一個常量的值必須是0

實際項目中使用的枚舉常量值經(jīng)常是從0開始的,這樣項目需求與protobuf3有沖突。
解決方法是,將第一個枚舉常量0定義為無效值,或者額外定義一個無效值(比如-1),Google API Guider中建議枚舉的第一個值為 ENUN_TYPE_UNSPECIFIED,即枚舉名_UNSPECIFIED,舉個例子:

enum BallTypeEnum {
    BALL_TYPE_UNSPECIFIED = 0;
    BASKETBALL = 1;
    FOOTBALL = 2;
}

這樣,讓默認的枚舉值與業(yè)務(wù)的相分離。

message類型:

Java中,message類型的默認值是DEFAULT_INSTANCE,其值相當(dāng)于空的message,即XXX.newBuilder().build(),這樣對message類型的判空操作就應(yīng)該是這樣:

// protobuf message
message User {
    int32 id = 1;
    string name = 2;
    string email = 3;
    Address address = 4;
}

message Address {
    string street = 1;
    string building = 2;
}

// Java
if (user.getAddress() != null && user.getAddress() != UserProto.Address.getDefaultInstance()) {
    ...
} else {
    ...
}

結(jié)語

盡管protobuf3有一些不方便的地方,但protobuf畢竟數(shù)據(jù)交換協(xié)議,負責(zé)交換數(shù)據(jù),所以建議在使用protobuf時,不要與具體業(yè)務(wù)耦合過緊,protobuf相關(guān)操作放在數(shù)據(jù)傳輸?shù)慕涌趯印?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,564評論 19 139
  • 由于工程項目中擬采用一種簡便高效的數(shù)據(jù)交換格式,百度了一下發(fā)現(xiàn)除了采用 xml、JSON 還有 ProtoBuf(...
    黃海佳閱讀 49,168評論 1 23
  • 翻譯查閱外網(wǎng)資料過程中遇到的比較優(yōu)秀的文章和資料,一是作為技術(shù)參考以便日后查閱,二是訓(xùn)練英文能力。此文翻譯自 Pr...
    401閱讀 69,129評論 1 39
  • 針對該款stm32芯片(stm32f107vct6)沒有軟件仿真庫的問題,設(shè)計了新的調(diào)試方式,即通過串口打印文件名...
    Westring閱讀 4,493評論 0 1
  • 1.我為什么要努力?因為我不想在一年之后所有的同學(xué)聚會的時候,仰望著誰的臉色,奉承別人的微笑;我不想在街上看到自己...
    sunshine_小丸子閱讀 362評論 4 5

友情鏈接更多精彩內(nèi)容