Protobuf - 語法、字段使用規則、注意事項

目錄

前言

一、Protobuf 基本語法

1.1、Protoc?版本?

1.2、文件格式配置

1.3、消息字段規則

1.3.1、字段數據類型

1.3.2、字段修飾規則

1.3.3、消息類型定義

1.3.4、enum 類型

1.3.5、Any 類型

1.3.6、oneof 類型

1.3.7、map 類型

1.3.8、默認值

1.3.9、更新消息規則

1.3.10、保留字段 reserved

1.3.11、選項 optional(了解,proto3 移除)


前言


前面在講?gRPC 的時候有講到?Protobuf 的語法,但實際上遠沒有這么簡單,有很多坑和注意事項,所以這篇文章就是來補坑的~

一、Protobuf 基本語法


1.1、Protoc?版本?

1.2、文件格式配置

a)創建文件:文件都是 proto 為后綴,例如 UserService.proto

b)基本內容:

// 設定使用的 proto 版本
syntax = "proto3";/**java_multiple_files = true 表示 Protobuf 編譯器會為每個定義的消息類型生成一個單獨的 Java 文件,而不是都放在一個文件中java_multiple_files = false 表示 Protobuf 編譯器會把所有的消息類型生成的 Java 代碼都放在一個文件中*/
option java_multiple_files = false;/**指定 protobuf 生成的類,放在哪個包中*/
option java_package = "org.cyk";/**指定 protobuf 生成的外部類的名字外部類是用來管理內部類的內部類才是開發中使用的*/
option java_outer_classname = "HelloProto";

c)導包:例如有 A.proto 和 B.proto 文件,現在需要在 B.proto 文件中引入 A.proto 文件的內容,就需要使用? import

import xxx/A.proto

1.3、消息字段規則

1.3.1、字段數據類型

消息中定義的數據類型(我們主要關心 .proto 對應的 Java/Kotlin 類型).

以下列表來自官網:Language Guide (proto 3) | Protocol Buffers Documentation

.proto TypeC++ TypeJava/Kotlin Type[1]Python Type[3]Go TypeRuby TypeC# TypePHP TypeDart Type
doubledoubledoublefloatfloat64Floatdoublefloatdouble
floatfloatfloatfloatfloat32Floatfloatfloatdouble
int32int32intintint32Fixnum or Bignum (as required)intintegerint
int64int64longint/long[4]int64Bignumlonginteger/string[6]Int64
uint32uint32int[2]int/long[4]uint32Fixnum or Bignum (as required)uintintegerint
uint64uint64long[2]int/long[4]uint64Bignumulonginteger/string[6]Int64
sint32int32intintint32Fixnum or Bignum (as required)intintegerint
sint64int64longint/long[4]int64Bignumlonginteger/string[6]Int64
fixed32uint32int[2]int/long[4]uint32Fixnum or Bignum (as required)uintintegerint
fixed64uint64long[2]int/long[4]uint64Bignumulonginteger/string[6]Int64
sfixed32int32intintint32Fixnum or Bignum (as required)intintegerint
sfixed64int64longint/long[4]int64Bignumlonginteger/string[6]Int64
boolboolbooleanboolboolTrueClass/FalseClassboolbooleanbool
stringstringStringstr/unicode[5]stringString (UTF-8)stringstringString
bytesstringByteStringstr (Python 2)
bytes (Python 3)
[]byteString (ASCII-8BIT)ByteStringstring

1.3.2、字段修飾規則

消息字段可以使用如下規則修飾:

  • singular(proto3 中默認使用此規則):表示該字段只能 null 或者是一個具體值.
  • repeated:表示為 Java 中的 List 類型.

例如如下:

syntax = "proto3";option java_multiple_files = false;
option java_package = "org.cyk";
option java_outer_classname = "UserProto";message Userinfo {string name = 1; // 這里的數字是字段的唯一標識,因為將來時面向字節流傳輸,需要讓每個字段能夠對應的上int32 age = 2;repeated string phone = 3;
}

1.3.3、消息類型定義

在單個 .proto 文件中可以定義多個消息,并且支持嵌套類型,不同消息體重的編碼可以重復.

syntax = "proto3";option java_multiple_files = false;
option java_package = "org.cyk";
option java_outer_classname = "UserProto";//1.非嵌套
message Userinfo1 {string name = 1;int32 age = 2;repeated string phone = 3;
}//2.嵌套
message Userinfo2 {string name = 1;int32 age = 2;repeated string phone = 3;message Stat {int32 rank = 1;int32 fans = 2;}
}//3.消息類型可作為字段使用
message Human {string aaa = 1;Userinfo1 userinfo = 2;
}

1.3.4、enum 類型

enum ArticlePubType {NORMAL = 0; //發布普通文章PRIVATE = 1; //發布私有文章TIMER = 2; //定時發布文章
}

規則如下:

  • 第一個枚舉值必須是 0.
  • 枚舉類型可以定義在消息外,也可以在定義在消息體內(嵌套).
  • 枚舉的常量值在 32 位整數范圍內.? 但因為負值無效,所以不建議使用(和編碼規則有關).
  • 同級(同一個文件下,或者是引入的其他 proto 文件)枚舉類型,枚舉值不能重名.

1.3.5、Any 類型

可以簡單的理解位 泛型.? ?因此 Any 中可以存儲任意消息類型.? 并且 Any 類型也可以使用 repeated 修飾.

Note:Any 類型是 google 已經定義好的類型,在 include 目錄下就可以找到所有 google 已經定義好的 .proto 文件.

import "google/protobuf/any.proto"; //引入 Anymessage Userinfo1 {string name = 1;int32 age = 2;repeated string phone = 3;google.protobuf.Any data = 4;
}

將來通過 protoc 編譯生成的 Java 文件中,給 Any 類型生成的對象提供了如下方法:

  • hasXXX:用來檢測當前字段是否被設置(這個方法存在的意義在于,字段即使不設置也是有默認值的,因此 has 就可以檢測到底是否真的有設置值).
  • setXXX:要求傳一個 Any 類型的對象.
  • 對于 Any 類型:
    • Any.pack(T message) 可以講任意消息類型轉化成 Any 類型.
    • message.getAny().unpack(Class<T> clazz) 方法可以將 Any 類型轉回之前設置的任意消息類型.
    • message.getAny().is(Class<T> clazz) 用來判斷存放的消息類型.

1.3.6、oneof 類型

如果消息中有很多可選字段,并且將來只有一個字段會被設置,那么就可以使用 oneof 來約束這個行為.

syntax = "proto3";option java_multiple_files = false;
option java_package = "org.cyk";
option java_outer_classname = "UserProto";import "google/protobuf/any.proto"; //引入 Anymessage Userinfo1 {string name = 1;int32 age = 2;repeated string phone = 3;google.protobuf.Any data = 4;oneof other_content {string qq = 5;string wechat = 6;}
}

注意事項:

  • 可選字段中的 字段編號 不能和 非可選字段 的編號沖突.
  • oneof 中不能使用 repeated 字段.
  • 如果將來 oneof 中有多個字段被設置了值,那么只會保留最后一個設置的成員,之前設置的 oneof 成員會自動清除.

oneof 將來生成 Java 代碼中會提供以下方法:

  • clear():清空 oneof 中的字段.
  • getXXXCase():獲取當前設置了哪些字段.
  • hasXXX():檢查當前字段是否被設置.

1.3.7、map 類型

類似于 Java 中的 HashMap,使用方式如下:

map<key_type>, value_type> map_field = N;

注意:

  • key_type 是除了 float 和 bytes 類型以外的任意標量類型.
  • value_type 可以是任意類型.
  • map 字段不可以用 repeated 修飾.

例如:

syntax = "proto3";option java_multiple_files = false;
option java_package = "org.cyk";
option java_outer_classname = "UserProto";import "google/protobuf/any.proto"; //引入 Anymessage Userinfo1 {string name = 1;int32 age = 2;repeated string phone = 3;google.protobuf.Any data = 4;oneof other_content {string qq = 5;string wechat = 6;}map<string, string> arguments = 7;
}

1.3.8、默認值

如果將來給服務端發送的消息對象中有一些字段沒有設置值,那么將來這些消息字段在反序列化時就會被設置默認值.? ?不同類型默認值不同:

類型默認值
字符串空字符串
字節空字節
布爾值false
數值類型0
枚舉默認是第一個定義的枚舉值,也就是 0(也必須是 0).
消息字段具體根據語言而定
repeated 修飾的字段空列表
消息字段、oneof字段、any字段有 has 方法來檢測當前字段是否被設置

1.3.9、更新消息規則

當現有消息類型已經不再滿足我們的需求,需要擴展一個字段的時候,要注意遵守以下規則:

a)禁止修改任何已有的字段編號.

例如你更新的這個 proto 文件中一個已有的字段編號,并且這個新版的 proto 文件被用于生成序列化代碼,但是服務端這邊反序列化代碼還是使用的舊代碼進行反序列化,這就可能導致數據丟失或者解析錯誤.

b)如果要刪除老字段,要保證不再使用刪除字段的編號.? 正確的做法是通過 reserved 保留字段編號,確保該編號不能重復使用.

因為如果我們只是簡單的刪除了某一個字段而不采取其他措施,那么就可能導致和 (a) 一樣的情況.

c)int32、uint32、int64、bool 之間是完全兼容的.? 也就是說這些類型中任意一個改成另一個,都不會破壞兼容性.? 不過還是要注意,如果從精度較高的字段轉化為精度較低的字段可能會被截斷.

例如 64位 當作 32位 讀取,雖然不存在兼容性問題,但會截斷 32 位.

d)新增一個字段到 oneof 類型是不安全的.

這個本質上 和 (a) 問題一致.? ?因為 oneof 如果被客戶端設置的字段是新增的字段,而服務端這邊還是使用舊的反序列化代碼解析,就可能會出現問題.

1.3.10、保留字段 reserved

如果通過刪除字段來更新消息,未來用戶在添加新字段時,可能會使用以前被刪除的字段編號.? 將來使用 proto 舊版本的程序就會引發很多問題.

那么為了確保不會發生這種情況的方法就是:使用 reserverd 將指定字段的 編號 或 名稱 設置位保留項.? 當我們再使用這些 編號 或 名稱 時,protocol 編譯器將會警告這些編號不可用.

1.3.11、選項 optional(了解,proto3 移除)

在 proto2 中 optional 是一個字段修飾符,標識字段在消息中是可選的(消息中可能包含該字段,也可能不包含). 但是從 proto3 開始,optional 就被移除了,并且所有字段都是可選的(因為他們都有默認值).?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/15503.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/15503.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/15503.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

css設置文字在固定寬度中等距分開(僅限于單行文本)

一、要實現的效果&#xff1a; 二、代碼 要在CSS中設置文本在一個固定寬度的容器中等距分開&#xff0c; 可以使用text-align: justify;屬性&#xff0c;它可以讓文本兩端對齊&#xff0c;看起來就像是等距分開的。 但是要注意&#xff0c;單獨使用text-align:justify;只能對單…

機器學習 - 模型訓練

機器學習&#xff08;Machine Learning&#xff0c;ML&#xff09;是利用計算機算法和統計模型&#xff0c;使計算機系統在沒有明確編程的情況下執行特定任務的過程。機器學習的整個過程可以分為以下幾個主要步驟&#xff1a; 訓練步驟 問題定義與需求分析 目標設定&#xff1…

【Qt】Qt多元素控件深入解析與實戰應用:列表(QListWidget)、表格(QTableWidget)與樹形(QTreeWidget)結構

文章目錄 前言&#xff1a;Qt中多元素控件&#xff1a;1. List Widget1.1. 代碼示例: 使用 ListWidget 2.Table Widget2.1. 代碼示例: 使用 QTableWidget 3. Tree Widget3.1. 代碼示例: 使用 QTreeWidget 總結&#xff1a; 前言&#xff1a; 在Qt框架中&#xff0c;用戶界面的…

2024.5.25

package com.Swork.file;import java.io.File; import java.io.IOException; import java.util.Date;public class Demo1 {public static void main(String[] args) {//1,構造文件對象System.out.println("1,構造文件對象");File file new File("D://Work//Fil…

C語言內存函數超詳細講解

個人主頁&#xff1a;C忠實粉絲 歡迎 點贊&#x1f44d; 收藏? 留言? 加關注&#x1f493;本文由 C忠實粉絲 原創 C語言內存函數超詳細講解 收錄于專欄【C語言學習】 本專欄旨在分享學習C語言學習的一點學習筆記&#xff0c;歡迎大家在評論區交流討論&#x1f48c; 目錄 1. m…

C++面向對象程序設計-北京大學-郭煒【課程筆記(十一)】

C面向對象程序設計-北京大學-郭煒【課程筆記&#xff08;十一&#xff09;】 1、string&#xff08;重要知識點&#xff09;1.2、string的賦值和鏈接1.3、比較string1.4、子串1.5、交換string1.6、尋找string中的字符1.7、刪除string中的字符1.8、替換string中的字符1.9、在str…

leetcode119-Pascal‘s Triangle II

題目 給定一個非負索引 rowIndex&#xff0c;返回「楊輝三角」的第 rowIndex 行。 在「楊輝三角」中&#xff0c;每個數是它左上方和右上方的數的和。 示例 1: 輸入: rowIndex 3 輸出: [1,3,3,1] 分析 楊輝三角每位數字就是上一行同一列&#xff0b;上一行前一列的和&#…

結構體;結構成員訪問操作符

結構體&#xff1a; 雖然c語言已經提供了內置類型&#xff0c;比如&#xff1a;char、short、int、long等&#xff0c;但還是不夠用&#xff0c;就好比我描述一個人&#xff0c;我需要描述他的身高&#xff0c;體重&#xff0c;年齡&#xff0c;名字等信息&#xff0c…

微軟密謀超級AI大模型!LangChain帶你輕松玩轉大模型開發

此前&#xff0c;據相關媒體報道&#xff0c;微軟正在研發一款名為MAI-1的最新AI大模型&#xff0c;其參數規模或將達5000億以上&#xff0c;遠超此前微軟推出的相關開源模型&#xff0c;其性能或能與谷歌的Gemini 1.5、Anthropic的Claude 3和OpenAI的GPT-4等知名大模型相匹敵。…

Linux文本處理三劍客(詳解)

一、文本三劍客是什么&#xff1f; 1. 對于接觸過Linux操作系統的人來說&#xff0c;應該都聽過說Linux中的文本三劍客吧&#xff0c;即awk、grep、sed&#xff0c;也是必須要掌握的Linux命令之一&#xff0c;三者都是用來處理文本的&#xff0c;但側重點各不相同&#xff0c;a…

Sam Altman微軟Build 2024最新演講:AI可能是下一個移動互聯網

大家好&#xff0c;我是木易&#xff0c;一個持續關注AI領域的互聯網技術產品經理&#xff0c;國內Top2本科&#xff0c;美國Top10 CS研究生&#xff0c;MBA。我堅信AI是普通人變強的“外掛”&#xff0c;所以創建了“AI信息Gap”這個公眾號&#xff0c;專注于分享AI全維度知識…

【C++11】lambda匿名函數和包裝器

目錄 一&#xff0c;lambda匿名函數 1-1&#xff0c;lambda的引入 1-2&#xff0c;lambda表達式書寫格式 1-3&#xff0c;lambda函數的名稱 1-4&#xff0c;lambda捕獲列表的使用 1-5&#xff0c;函數對象與lambda表達式 二&#xff0c;包裝器 2-1&#xff0c;function…

信息系統管理工程師知識點

信息系統管理工程師知識點 損壞包括自然災害、物理損壞&#xff08;磁盤壞、設備使用壽命&#xff0c;外力破損&#xff09;、設備故障&#xff08;停電、電磁干擾&#xff09;。 泄漏包括電磁輻射&#xff08;偵聽微機損傷過程&#xff09;、乘機而入&#xff08;合法用戶進…

一天了解一個機器學習模型——機器學習基礎知識

人工智能的兩大任務——預測和決策 預測包括對輸入目標的模式識別、標簽分類、回歸、預測未來數據、聚類 決策需要機器產生行動&#xff0c;改變狀態&#xff0c;如下圍棋、自動駕駛 支持人工智能的四大類技術 搜索——結合算法探索分支的好壞&#xff0c;從而做出決策&…

如何使用maven運行SpringBoot程序?

目錄 一、什么是maven 二、什么是SpringBoot 三、如何使用maven運行SpringBoot程序&#xff1f; 一、什么是maven Maven&#xff1a;簡化Java項目構建的自動化工具 在軟件開發的世界里&#xff0c;Maven以其強大的項目管理和構建自動化功能&#xff0c;為Java開發者提供了…

內存泄漏及其解決方法

1. 系統崩潰前的現象 垃圾回收時間延長&#xff1a;從原本的約10ms增長至50ms&#xff0c;Full GC時間也由0.5s增加至4-5s。Full GC頻率增加&#xff1a;最短間隔可縮短至1分鐘內發生一次。年老代內存持續增長&#xff1a;即使經過Full GC&#xff0c;年老代內存未見明顯釋放。…

容器化:ES和Kibana

1 緣起 最近在學習使用ES&#xff0c; 為了找一個功能強大的可視化工具&#xff0c;之前使用了ES-Head&#xff0c;可以滿足學習需求。 閑暇時間又折騰了另一個工具Kibana&#xff0c; 分享如下。 Kibana優點&#xff1a; 用戶友好性&#xff1a;Kibana提供直觀易用的用戶界面…

Strategy設計模式

Strategy設計模式舉例。 看圖&#xff1a; 代碼實現&#xff1a; #include <iostream>using namespace std;class FlyBehavior { public:virtual void fly() 0; };class QuackBehavior { public:virtual void quack() 0; };class FlyWithWings :public FlyBehavior …

數據庫(vb.net+OleDB+Access)簡易學生信息管理系統

在我們日常生活當中&#xff0c;數據庫一詞往往離不開我們的編程界&#xff0c;在學校、倉庫等方面起著存儲數據及數據關系作用的文件。相較于Excel&#xff0c;Access可以存儲無限多的記錄&#xff0c;內容也十分豐富&#xff0c;例如文本、數字、日期、T&F等。而且不需要…

k8s命令式對象管理和配置

kubectl補全: # dnf install -y bash-completion # echo "source <(kubectl completion bash)" >> ~/.bashrc # kubectl completion bash > /etc/bash_completion.d/kubectl 命令式對象管理 kubectl命令 # 查看所有pod kubectl get pod # 查看某個po…