欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go protobuf?詳解

 更新時間:2024年01月04日 10:35:42   作者:野生的狒狒  
Protobuf是Protocol Buffers的簡稱,它是Google公司開發(fā)的一種數(shù)據(jù)描述語言,是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲格式,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化,或者說序列化,這篇文章主要介紹了protobuf?詳解,需要的朋友可以參考下

protobuf簡介

Protobuf是Protocol Buffers的簡稱,它是Google公司開發(fā)的一種數(shù)據(jù)描述語言,是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲格式,可以用于結(jié)構(gòu)化數(shù)據(jù)串行化,或者說序列化 。它很適合做數(shù)據(jù)存儲或 RPC 數(shù)據(jù)交換格式??捎糜谕ㄓ崊f(xié)議、數(shù)據(jù)存儲等領(lǐng)域的語言無關(guān)、平臺無關(guān)、可擴展的序列化結(jié)構(gòu)數(shù)據(jù)格式。目前提供了 C++、Java、Python 三種語言的 API。

  • protobuf是類似與json一樣的數(shù)據(jù)描述語言(數(shù)據(jù)格式)
  • protobuf非常適合于RPC數(shù)據(jù)交換格式

注意:protobuf本身并不是和gRPC綁定的。它也可以被用于非RPC場景,如存儲等

protobuf的優(yōu)劣勢

1)優(yōu)勢:

  • 序列化后體積相比Json和XML很小,適合網(wǎng)絡傳輸
  • 序列化反序列化速度很快,快于Json的處理速度
  • 消息格式升級和兼容性還不錯
  • 支持跨平臺多語言

2)劣勢:

  • 應用不夠廣(相比xml和json)
  • 二進制格式導致可讀性差
  • 缺乏自描述

protoc安裝(windows)

protoc就是protobuf的編譯器,它把proto文件編譯成不同的語言

下載安裝protoc編譯器(protoc)

下載protobuf:https://github.com/protocolbuffers/protobuf/releases/download/v3.20.1/protoc-3.20.1-win64.zip

解壓后,將目錄中的 bin 目錄的路徑添加到系統(tǒng)環(huán)境變量,然后打開cmd輸入protoc查看輸出信息,此時則安裝成功

安裝protocbuf的go插件(protoc-gen-go)

由于protobuf并沒直接支持go語言需要我們手動安裝相關(guān)插件

protocol buffer編譯器需要一個插件來根據(jù)提供的proto文件生成 Go 代碼,Go1.16+要使用下面的命令安裝插件:

 go install google.golang.org/protobuf/cmd/protoc-gen-go@latest  // 目前最新版是v1.3.0

安裝grpc(grpc)

 go get -u -v google.golang.org/grpc@latest    // 目前最新版是v1.53.0

安裝grpc的go插件(protoc-gen-go-grpc)

說明:在google.golang.org/protobuf中,protoc-gen-go純粹用來生成pb序列化相關(guān)的文件,不再承載gRPC代碼生成功能,所以如果要生成grpc相關(guān)的代碼需要安裝grpc-go相關(guān)的插件:protoc-gen-go-grpc

 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest  // 目前最新版是v1.3.0

protobuf語法

protobuf語法

類型:類型不僅可以是標量類型(intstring等),也可以是復合類型(enum等),也可以是其他message

字段名:字段名比較推薦的是使用下劃線/分隔名稱

字段編號:一個message內(nèi)每一個字段編號都必須唯一的,在編碼后其實傳遞的是這個編號而不是字段名

字段規(guī)則:消息字段可以是以下字段之一

singular:格式正確的消息可以有零個或一個字段(但不能超過一個)。使用 proto3 語法時,如果未為給定字段指定其他字段規(guī)則,則這是默認字段規(guī)則

optional:與 singular 相同,不過可以檢查該值是否明確設(shè)置

repeated:在格式正確的消息中,此字段類型可以重復零次或多次。系統(tǒng)會保留重復值的順序

map:這是一個成對的鍵值對字段

保留字段:為了避免再次使用到已移除的字段可以設(shè)定保留字段。如果任何未來用戶嘗試使用這些字段標識符,編譯器就會報錯

簡單語法

proto文件基本語法

 syntax = "proto3";              // 指定版本信息,不指定會報錯
 package pb;                     // 后期生成go文件的包名
 // message為關(guān)鍵字,作用為定義一種消息類型
 message Person{
     string name = 1;   // 名字
     int32  age = 2 ;   // 年齡
 }
 ?
 enum test{
     int32 age = 0;
 }

protobuf消息的定義(或者稱為描述)通常都寫在一個以 .proto 結(jié)尾的文件中:

  • 第一行指定正在使用proto3語法:如果不這樣做,協(xié)議緩沖區(qū)編譯器將假定正在使用proto2(這也必須是文件的第一個非空的非注釋行)
  • 第二行package指明當前是pb包(生成go文件之后和Go的包名保持一致)
  • message關(guān)鍵字定義一個Person消息體,類似于go語言中的結(jié)構(gòu)體,是包含一系列類型數(shù)據(jù)的集合。
    • 許多標準的簡單數(shù)據(jù)類型都可以作為字段類型,包括bool,int32, floatdouble,和string
    • 也可以使用其他message類型作為字段類型。

在message中有一個字符串類型的value成員,該成員編碼時用1代替名字。在json中是通過成員的名字來綁定對應的數(shù)據(jù),但是Protobuf編碼卻是通過成員的唯一編號來綁定對應的數(shù)據(jù),因此Protobuf編碼后數(shù)據(jù)的體積會比較小,能夠快速傳輸,缺點是不利于閱讀。

message常見的數(shù)據(jù)類型與go中類型對比

.proto類型Go類型介紹
doublefloat6464位浮點數(shù)
floatfloat3232位浮點數(shù)
int32int32使用可變長度編碼。編碼負數(shù)效率低下——如果你的字段可能有負值,請改用sint32。
int64int64使用可變長度編碼。編碼負數(shù)效率低下——如果你的字段可能有負值,請改用sint64。
uint32uint32使用可變長度編碼。
uint64uint64使用可變長度編碼。
sint32int32使用可變長度編碼。符號整型值。這些比常規(guī)int32s編碼負數(shù)更有效。
sint64int64使用可變長度編碼。符號整型值。這些比常規(guī)int64s編碼負數(shù)更有效。
fixed32uint32總是四字節(jié)。如果值通常大于228,則比uint 32更有效
fixed64uint64總是八字節(jié)。如果值通常大于256,則比uint64更有效
sfixed32int32總是四字節(jié)。
sfixed64int64總是八字節(jié)。
boolbool布爾類型
stringstring字符串必須始終包含UTF - 8編碼或7位ASCII文本
bytes[]byte可以包含任意字節(jié)序列

protobuff語法進階

message嵌套

messsage除了能放簡單數(shù)據(jù)類型外,還能存放另外的message類型:

syntax = "proto3";          // 指定版本信息,不指定會報錯
 package pb;                 // 后期生成go文件的包名
 // message為關(guān)鍵字,作用為定義一種消息類型
 message Person{
     string name = 1;  // 名字
     int32  age = 2 ;  // 年齡
     // 定義一個message
     message PhoneNumber {
         string number = 1;
         int64 type = 2;
     }
     PhoneNumber phone = 3;
 }

message成員編號,可以不從1開始,但是不能重復,不能使用19000 - 19999

repeated關(guān)鍵字

repeadted關(guān)鍵字類似與go中的切片,編譯之后對應的也是go的切片,用法如下:

 syntax = "proto3";              // 指定版本信息,不指定會報錯
 package pb;                     // 后期生成go文件的包名
 // message為關(guān)鍵字,作用為定義一種消息類型
 message Person{
     string name = 1;   // 名字
     int32  age = 2 ;   // 年齡
     // 定義一個message
     message PhoneNumber {
         string number = 1;
         int64 type = 2;
     }
     repeated PhoneNumber phone = 3;
 }

默認值

解析數(shù)據(jù)時,如果編碼的消息不包含特定的單數(shù)元素,則解析對象對象中的相應字段將設(shè)置為該字段的默認值

不同類型的默認值不同,具體如下:

  • 對于字符串,默認值為空字符串
  • 對于字節(jié),默認值為空字節(jié)
  • 對于bools,默認值為false
  • 對于數(shù)字類型,默認值為零
  • 對于枚舉,默認值是第一個定義的枚舉值,該值必須為0。
  • repeated字段默認值是空列表
  • message字段的默認值為空對象

enum關(guān)鍵字

在定義消息類型時,可能會希望其中一個字段有一個預定義的值列表

比如說,電話號碼字段有個類型,這個類型可以是,home,work,mobile

我們可以通過enum在消息定義中添加每個可能值的常量來非常簡單的執(zhí)行此操作。示例如下:

syntax = "proto3";              // 指定版本信息,不指定會報錯
 package pb;                     // 后期生成go文件的包名
 // message為關(guān)鍵字,作用為定義一種消息類型
 message Person{
     string name = 1;   // 名字
     int32  age = 2 ;   // 年齡
     // 定義一個message
     message PhoneNumber {
         string number = 1;
         PhoneType type = 2;
     }
     repeated PhoneNumber phone = 3;
 }
 ?
 // enum為關(guān)鍵字,作用為定義一種枚舉類型
 enum PhoneType {
     MOBILE = 0;
     HOME = 1;
     WORK = 2;
 }

如上,enum的第一個常量映射為0,每個枚舉定義必須包含一個映射到零的常量作為其第一個元素。這是因為:

必須有一個零值,以便我們可以使用0作為數(shù)字默認值。

零值必須是第一個元素,以便與proto2語義兼容,其中第一個枚舉值始終是默認值。

enum還可以為不同的枚舉常量指定相同的值來定義別名。如果想要使用這個功能必須將allow_alias選項設(shè)置為true,負責編譯器將報錯。示例如下:

syntax = "proto3";              // 指定版本信息,不指定會報錯
 package pb;                     // 后期生成go文件的包名
 // message為關(guān)鍵字,作用為定義一種消息類型
 message Person{
     string name = 1;   // 名字
     int32  age = 2 ;   // 年齡
     // 定義一個message
     message PhoneNumber {
         string number = 1;
         PhoneType type = 2;
     }
     repeated PhoneNumber phone = 3;
 }
 ?
 // enum為關(guān)鍵字,作用為定義一種枚舉類型
 enum PhoneType {
     // 如果不設(shè)置將報錯
     option allow_alias = true;
     MOBILE = 0;
     HOME = 1;
     WORK = 2;
     Personal = 2;
 }

oneof關(guān)鍵字

如果有一個包含許多字段的消息,并且最多只能同時設(shè)置其中的一個字段,則可以使用oneof功能,示例如下:

 message Person{
     string name = 1; // 名字
     int32  age = 2 ; // 年齡
     //定義一個message
     message PhoneNumber {
         string number = 1;
         PhoneType type = 2;
     }
 ?
     repeated PhoneNumber phone = 3;
     oneof data{
         string school = 5;
         int32 score = 6;
     }
 }

定義RPC服務

如果需要將message與RPC一起使用,則可以在.proto文件中定義RPC服務接口,protobuf編譯器將根據(jù)你選擇的語言生成RPC接口代碼。示例如下:

//定義RPC服務
 service HelloService {
     rpc Hello (Person)returns (Person);
 }

注意:默認protobuf編譯期間,不編譯服務,如果要想讓其編譯,需要使用gRPC

protobuf編譯

編譯器調(diào)用

protobuf 編譯是通過編譯器 protoc 進行的,通過這個編譯器,我們可以把 .proto 文件生成 go,Java,Python,C++, Ruby或者C# 代碼

可以使用以下命令來通過 .proto 文件生成go代碼(以及grpc代碼)

// 將當前目錄中的所有 .proto文件進行編譯生成go代碼
 protoc --go_out=./ --go_opt=paths=source_relative *.proto

protobuf 編譯器會把 .proto 文件編譯成 .pd.go 文件

--go_out 參數(shù)

作用:指定go代碼生成的基本路徑

  • protocol buffer編譯器會將生成的Go代碼輸出到命令行參數(shù)go_out指定的位置
  • go_out標志的參數(shù)是你希望編譯器編寫 Go 輸出的目錄
  • 編譯器會為每個.proto 文件輸入創(chuàng)建一個源文件
  • 輸出文件的名稱是通過將.proto 擴展名替換為.pb.go 而創(chuàng)建的

--go_opt 參數(shù)

protoc-gen-go提供了--go_opt參數(shù)來為其指定參數(shù),可以設(shè)置多個:

paths=import:生成的文件會按go_package路徑來生成,當然是在--go_out目錄

例如,go_out/$go_package/pb_filename.pb.go

如果未指定路徑標志,這就是默認輸出模式

paths=source_relative:輸出文件與輸入文件放在相同的目錄中

例如,一個protos/buzz.proto輸入文件會產(chǎn)生一個位于protos/buzz.pb.go的輸出文件。

module=$PREFIX:輸出文件放在以 Go 包的導入路徑命名的目錄中,但是從輸出文件名中刪除了指定的目錄前綴。

例如,輸入文件 pros/buzz.proto,其導入路徑為 example.com/project/protos/fizz 并指定example.com/projectmodule前綴,結(jié)果會產(chǎn)生一個名為 pros/fizz/buzz.pb.go 的輸出文件。

在module路徑之外生成任何 Go 包都會導致錯誤,此模式對于將生成的文件直接輸出到 Go 模塊非常有用。

--proto_path 參數(shù)

--proto_path=IMPORT_PATH

  • IMPORT_PATH是 .proto 文件所在的路徑,如果忽略則默認當前目錄。
  • 如果有多個目錄則可以多次調(diào)用--proto_path,它們將會順序的被訪問并執(zhí)行導入。

使用示例:

protoc --proto_path=src --go_out=out --go_opt=paths=source_relative foo.proto bar/baz.proto
 // 編譯器將從 `src` 目錄中讀取輸入文件 `foo.proto` 和 `bar/baz.proto`,并將輸出文件 `foo.pb.go` 和 `bar/baz.pb.go` 寫入 `out` 目錄。如果需要,編譯器會自動創(chuàng)建嵌套的輸出子目錄,但不會創(chuàng)建輸出目錄本身

使用grpc的go插件 安裝proto-gen-go-grpc

google.golang.org/protobuf中,protoc-gen-go純粹用來生成pb序列化相關(guān)的文件,不再承載gRPC代碼生成功能。生成gRPC相關(guān)代碼需要安裝grpc-go相關(guān)的插件protoc-gen-go-grpc

// 安裝protoc-gen-go-grpc
 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest  // 目前最新版是v1.3.0

生成grpc的go代碼:

// 主要是--go_grpc_out參數(shù)會生成go代碼
 protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative  *.proto

--go-grpc_out 參數(shù)

作用:指定grpc go代碼生成的基本路徑

命令會產(chǎn)生的go文件:

  • protoc-gen-go:包含所有類型的序列化和反序列化的go代碼
  • protoc-gen-go-grpc:包含service中的用來給client調(diào)用的接口定義以及service中的用來給服務端實現(xiàn)的接口定義

--go-grpc_opt 參數(shù)

protoc-gen-go類似,protoc-gen-go-grpc提供 --go-grpc_opt 來指定參數(shù),并可以設(shè)置多個

github.com/golang/protobuf 和 google.golang.org/protobuf github.com/golang/protobuf

  • github.com/golang/protobuf 現(xiàn)在已經(jīng)廢棄
  • 它可以同時生成pb和gRPC相關(guān)代碼的

用法:

// 它在--go_out加了plugin關(guān)鍵字,paths參數(shù)有兩個選項,分別是 import 和 source_relative
 --go_out=plugins=grpc,paths=import:.  *.proto

google.golang.org/protobuf

  • github.com/golang/protobuf的升級版本,v1.4.0之后github.com/golang/protobuf僅是google.golang.org/protobuf的包裝
  • 它純粹用來生成pb序列化相關(guān)的文件,不再承載gRPC代碼生成功能,生成gRPC相關(guān)代碼需要安裝grpc-go相關(guān)的插件protoc-gen-go-grpc

用法:

// 它額外添加了參數(shù)--go-grpc_out以調(diào)用protoc-gen-go-grpc插件生成grpc代碼
 protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relativ

到此這篇關(guān)于protobuf 詳解的文章就介紹到這了,更多相關(guān)protobuf 詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang mysql的連接池的具體使用

    golang mysql的連接池的具體使用

    本文主要介紹了golang mysql的連接池的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • 從并發(fā)到并行解析Go語言中的sync.WaitGroup

    從并發(fā)到并行解析Go語言中的sync.WaitGroup

    Go?語言提供了許多工具和機制來實現(xiàn)并發(fā)編程,其中之一就是?sync.WaitGroup。本文就來深入討論?sync.WaitGroup,探索其工作原理和在實際應用中的使用方法吧
    2023-05-05
  • 詳解Go語言中配置文件使用與日志配置

    詳解Go語言中配置文件使用與日志配置

    這篇文章主要為大家詳細講解一下Go語言中調(diào)整項目目錄結(jié)構(gòu)、增加配置文件使用和增加日志配置的方法,文中示例代碼講解詳細,需要的可以參考一下
    2022-06-06
  • Go語言實現(xiàn)彩色輸出示例詳解

    Go語言實現(xiàn)彩色輸出示例詳解

    這篇文章主要為大家介紹了Go語言實現(xiàn)彩色輸出示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 淺析Go語言中的逃逸分析

    淺析Go語言中的逃逸分析

    逃逸分析算是go語言的特色之一,所以這篇文章小編就來和大家聊聊為什么不應該過度關(guān)注go語言的逃逸分析,感興趣的小伙伴可以跟隨小編一起了解一下
    2024-10-10
  • go實現(xiàn)Redis讀寫分離示例詳解

    go實現(xiàn)Redis讀寫分離示例詳解

    本篇文章將介紹Redis通信協(xié)議RESP,?而后在使用go來編寫一個中間件,從而來完成Redis讀寫分離,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Go實現(xiàn)凱撒密碼加密解密

    Go實現(xiàn)凱撒密碼加密解密

    這篇文章主要為大家介紹了Go實現(xiàn)凱撒密碼加密解密示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 使用自定義錯誤碼攔截grpc內(nèi)部狀態(tài)碼問題

    使用自定義錯誤碼攔截grpc內(nèi)部狀態(tài)碼問題

    這篇文章主要介紹了使用自定義錯誤碼攔截grpc內(nèi)部狀態(tài)碼問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 分享6個Go處理字符串的技巧小結(jié)

    分享6個Go處理字符串的技巧小結(jié)

    這篇文章主要介紹了分享6個Go處理字符串的技巧小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • golang return省略用法說明

    golang return省略用法說明

    這篇文章主要介紹了golang return省略用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評論