53. Protocol buffer 的Go使用

文章目錄

  • 一、介紹
  • 二、安裝
  • 三、protoc3語法
    • 1、 protoc3 與 protoc2區別
    • 2、proto3生成go代碼
      • Message
      • 內嵌Message
      • 字段
        • 單一標量字段
        • 單一message字段
        • 可重復字段slice
        • map字段
        • 枚舉

一、介紹

ProtobufGoogle旗下的一款平臺無關,語言無關,可擴展的序列化結構數據格式。所以很適合用做數據存儲和作為不同應用,不同語言之間相互通信的數據交換格式,只要實現相同的協議格式,即同一proto文件被編譯成不同的語言版本,加入到各自的工程中去,這樣不同語言就可以解析其他語言通過Protobuf序列化的數據。目前官網提供了C++,Python,JAVA,GO等語言的支持。

二、安裝

  1. Mac上安裝Protoc3
  2. Windows安裝Protoc3
  3. 安裝protoc-gen-go
    protoc-gen-go是生成Go代碼的protocolbuffers編譯器。可以理解為一個編譯器插件,配合protoc來使用。在命令行執行如下命令即可完成安裝:
go get -u github.com/golang/protobuf/protoc-gen-go@latest

網上資料推薦的基本都是這個命令,但目前該模塊已被棄用,繼續使用該命令將出現錯誤,提示該庫已經被棄用,讓我們使用go get -u google.golang.org/protobuf/

三、protoc3語法

1、 protoc3 與 protoc2區別

proto3proto2的基礎上去掉了一些復雜的語法和特性,更強調約定而弱化語法。主要幾點區別如下:

  1. proto文件第一行非空白非注釋行,必須指定版本,syntax = "proto3";如果不指定,則默認是proto2
  2. 字段規則移除了 required,并把 optional改名為 singular,省略不寫時,默認就是singular
  3. repeated字段默認采用 packed 編碼,在 proto2 中,需要明確使用[packed=true] 來為字段指定比較緊湊的 packed 編碼方式。
  4. 語言增加 Go、Ruby、JavaNano 支持,即在proto2時并不支持go語言。
  5. 移除了default 選項,在proto2中,可以使用default選項為某一字段指定默認值。在 proto3 中,字段的默認值只能根據字段類型由系統決定。也就是說,默認值全部是約定好的,而不再提供指定默認值的語法。在字段被設置為默認值的時候,該字段不會被序列化。這樣可以節省空間,提高效率。
    但這樣就無法區分某字段是根本沒賦值,還是賦值了默認值。 所以一般需要避免將默認值作為任何行為的觸發方式。例如
enum AudienceDisplayTypeEnum {NoValue = 0; // (占位符)說明端上沒有傳入此參數,請勿使用CurrentCount = 1; // 展示當前直播間內人數AccumulativeCount = 2; // 展示直播間累計人數SettingEntranceClosed = 99; // 端上拿到則不展示此選項,相當于配置項是否出現的開關
}

此例子是控制直播間展示在線人數還是看播人次的開關,開關僅兩個取值:truefalse,但這里并沒有使用bool類型,因為bool型默認值是false,即使前端沒有給我們傳該值,我們也會拿到false值,從而可能當成是前端傳過來的值,切換開關,因此使用枚舉。使用枚舉后,不使用01表示開關的打開與關閉,因為0是枚舉的默認值,也不應該作為控制行為的值,因此有業務含義的從序號為1的字段開始。
6. 枚舉類型的第一個字段必須為 0,因為枚舉會把第一個字段作為默認值
7. 增加了JSON映射特性,如

message XXXRequest {string  name = 1; int64 begin_time = 2 (go.tag = "json:\"beginTime\"");int64 end_time = 3;int32 page_no = 4;int32 page_size = 5;
}

2、proto3生成go代碼

Go Proto Buffer代碼生成官網文檔地址

如果一個.proto文件中有包聲明,生成的源代碼將會使用它來作為Go的包名,如果.proto的包名中有. ,在Go包名中會將.轉換為_。舉例來說proto包名example.high_score將會生成Go包名example_high_score

.proto文件中可以使用option go_package指令來覆蓋上面默認生成Go包名的規則。比如說包含如下指令的一個.proto文件

package example.high_score;
option go_package = "/test";

生成的Go源代碼的包名是test

如果一個.proto文件中不包含package聲明,生成的源代碼將會使用.proto文件的文件名作為Go包名,.會被首先轉換為_。舉例來說一個名為high.score.proto不包含package聲明的文件將會生成文件high.score.pb.go,他的Go包名是high_score

Message

一個簡單的message聲明:

message Foo {}

protocol buffer編譯器將會生成一個名為Foo的結構體,var A *Foo為實現了proto.Message接口的Foo類型的指針,因為Foo實現了proto.Message接口中ProtoMessage()方法,生成的XXX.pb.go文件將包含如下代碼片段,注意看注釋哦

type Foo struct {
}// 重置proto為默認值
func (m *Foo) Reset()         { *m = Foo{} }// String 返回proto的字符串表示
func (m *Foo) String() string { return proto.CompactTextString(m) }// ProtoMessage作為一個tag 確保其他人不會意外的實現
// proto.Message 接口.
func (*Foo) ProtoMessage()    {}

內嵌Message

一個message可以聲明在其他message的內部。比如:

message Foo {message Bar {}
}

這種情況,編譯器會生成兩個結構體:FooFoo_Bar

字段

編譯器會為每個在message中定義的字段生成一個Go結構體的字段,字段的確切性質取決于它的類型以及它是singular,repeated,map還是oneof字段。

注意生成的Go結構體的字段將始終使用駝峰命名,即在.proto文件中消息字段用的是小寫加下劃線(工作中基本都是這種形式),生成的Go代碼會是大駝峰命名。大小寫轉換的原理如下:

  • 首字母會大寫,如果message中字段的第一個字符是_,它將被替換為X
  • 如果內部下劃線后跟小寫字母,則刪除下劃線,并將后面跟隨的字母大寫。
    因此,proto字段foo_bar_bazGo中變成FooBarBaz _my_field_name變為XMyFieldName
單一標量字段

對于包級別字段定義:

int32 id = 1;

編譯器將生成一個帶有名為Idint32字段和一個訪問器方法GetId()的結構,該方法返回結構體中Id字段的零值(如果字段未設置(數值型零值為0,字符串為空字符串))。

單一message字段

給出如下消息類型

message Bar {}

對于一個有Bar類型字段的消息:

// proto3
message Baz {Bar foo = 1;
}

編譯器將會生成一個Go結構體

type Baz struct {Foo *Bar
}

消息類型的字段可以設置為nil,這意味著該字段未設置。

編譯器還生成一個func(m *Baz)GetFoo() *Bar輔助函數。這讓不在中間檢查nil值進行鏈式調用成為可能,因為該方法中會進行相關字段的nil判斷。

可重復字段slice

每個重復的字段在Go中的結構中生成一個T類型的slice,其中T是字段的元素類型。對于帶有重復字段的消息:

message Baz {repeated Bar foo = 1;
}

編譯器會生成如下結構體:

type Baz struct {Foo  []*Bar
}

同樣,對于字段定義repeated bytes foo = 1; 編譯器將會生成一個帶有類型為[][]byte, 名為Foo的字段的Go結構體。對于可重復的枚舉repeated MyEnum bar = 2;,編譯器會生成帶有類型為[]MyEnum, 名為Bar的字段的Go結構體。

map字段

每個映射字段會在Go的結構體中生成一個map[TKey]TValue類型的字段,其中TKey是字段的鍵類型,TValue是字段的值類型。對于下面這個消息定義:

message Bar {}message Baz {map<string, Bar> foo = 1;
}

編譯器生成Go結構體

type Baz struct {Foo map[string]*Bar
}
枚舉

給出如下枚舉

message SearchRequest {enum Corpus {UNIVERSAL = 0;WEB = 1;IMAGES = 2;LOCAL = 3;NEWS = 4;PRODUCTS = 5;VIDEO = 6;}Corpus corpus = 1;
}

編譯器將會生成一個枚舉類型和一系列該類型的常量。

對于消息中的枚舉(像上面那樣),類型名字以消息名開頭

type SearchRequest_Corpus int32

對于包級別的枚舉:

// .proto
enum Foo {DEFAULT_BAR = 0;BAR_BELLS = 1;BAR_B_CUE = 2;
}

Go中的類型不會對proto中的枚舉名稱進行修改:

type Foo int32

此類型具有String()方法,該方法返回給定值的名稱。

Enum()方法使用給定值初始化新分配的內存并返回相應的指針:

func (Foo) Enum() *Foo

編譯器為枚舉中的每個值生成一個常量。對于消息中的枚舉,常量以消息的名稱開頭:

const (SearchRequest_UNIVERSAL SearchRequest_Corpus = 0SearchRequest_WEB       SearchRequest_Corpus = 1SearchRequest_IMAGES    SearchRequest_Corpus = 2SearchRequest_LOCAL     SearchRequest_Corpus = 3SearchRequest_NEWS      SearchRequest_Corpus = 4SearchRequest_PRODUCTS  SearchRequest_Corpus = 5SearchRequest_VIDEO     SearchRequest_Corpus = 6
)

對于包級別的枚舉,常量以枚舉名稱開頭:

const (Foo_DEFAULT_BAR Foo = 0Foo_BAR_BELLS   Foo = 1Foo_BAR_B_CUE   Foo = 2
)

protobuf編譯器還生成從整數值到字符串名稱的映射以及從名稱到值的映射:

var Foo_name = map[int32]string{0: "DEFAULT_BAR",1: "BAR_BELLS",2: "BAR_B_CUE",
}
var Foo_value = map[string]int32{"DEFAULT_BAR": 0,"BAR_BELLS":   1,"BAR_B_CUE":   2,
}

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

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

相關文章

AWS KeyPair密鑰格式轉換PPK<>PEM

概述說明 PEM&#xff08;Privacy Enhanced Mail&#xff09;和PPK&#xff08;Putty Private Key&#xff09;都是與加密和安全相關的文件格式&#xff0c;通常用于存儲私鑰信息。它們在不同的上下文中使用&#xff0c;并且與不同的軟件和協議相關聯。 PEM&#xff08;Priva…

【kubernetes】k3s集群搭建(正在更新……)

文章目錄 一、k3s簡介二、快速搭建1.控制平面2.鏡像加速 Pod容器集1.創建和管理pod Deployment(部署)與ReplicaSet(副本集)滾動更新 Service命名空間YAML語法管理對象常用命令縮寫YAML規范 聲明式配置對象標簽選擇器 容器運行時接口(CRI)與鏡像導入導出容器運行時接口(CRI) 金絲…

基于POSIX標準的Linux進程間通信

文章目錄 1 管道&#xff08;匿名管道&#xff09;1.1 管道抽象1.2 接口——pipe1.3 管道的特征1.4 管道的四種情況1.5 匿名管道用例 2 命名管道2.1 創建一個命名管道——mkfifo2.2 關閉一個管道文件——unlink2.3 管道和命名管道的補充2.4 命名管道用例 3 共享內存3.1 原理3.2…

案例二:SQL Server數據庫的備份和還原

1、備份類型。 在 SQL Server 中提供了三種常用的備份類型&#xff0c;分別是完整備份&#xff0e;差異備份和事務日志備份。 完整備份&#xff1a; 完整備份包括對整個數據庫、部分事務日志、數據庫結構和文件結構的備份。完整備份代表的是備份完成時刻的數據庫。 完整備份是…

【Hydro】Python繪制降雨徑流雙Y軸成果圖

目錄 說明源代碼說明 雙y軸圖像具有單y軸圖像沒有的對比效果,通常會用來繪制降雨徑流成果圖,在MATLAB中有plotyy函數可以實現,Python的實現方式沒有MATLAB那樣方便,不過實現效果卻也不見得差。 Python中的matplotlib通常使用twinx來生成雙Y軸,下圖便是使用matplotlib繪制…

8、操作符重載

友元 可以通過friend關鍵字&#xff0c;把一個全局函數、另一個類的成員函數或者另一個類整體&#xff0c;聲明為授權類的友元友元擁有訪問授權類任何非公有成員的特權友元聲明可以出現在授權類的公有、私有或者保護等任何區域且不受訪問控制限定符的約束友元不是成員&#xf…

elment-table設置el-table-column的label里面的文字換行居中顯示

效果圖如下&#xff1a; 直接上代碼&#xff1a; <el-table class"ut-mt-2" row-key"company" default-expand-all:data"stateQuery.data" style"width: 100%":tree-props"{ children: departList, hasChildren: hasChildre…

Si24R03—低功耗 SOC 芯片(集成RISC-V內核+2.4GHz無線收發器)

Si24R03是一款高度集成的低功耗SOC芯片&#xff0c;其集成了基于RISC-V核的低功耗MCU和工作在2.4GHz ISM頻段的無線收發器模塊。 MCU模塊具有低功耗、Low Pin Count、寬電壓工作范圍&#xff0c;集成了13/14/15/16位精度的ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC等豐…

PandoraFMS 監控軟件 任意文件上傳漏洞復現

0x01 產品簡介 Pandora FMS 是用于監控計算機網絡的軟件。 Pandora FMS 允許以可視化方式監控來自不同操作系統、服務器、應用程序和硬件系統(例如防火墻、代理、數據庫、Web 服務器或路由器)的多個參數的狀態和性能。 0x02 漏洞概述 PandoraFMS upload_head_image.php 接…

.bat文件設置窗口標題、窗口大小、字體及背景顏色?

設置cmd窗口的標題 1、打開.bat文件編輯 2、輸入命令&#xff1a; title&#xff08;窗口標題&#xff09; 比如&#xff1a;title計算機 3、保存 4、雙擊運行.bat文件 &#xff0c;窗口標題改變成功 改變窗口大小 1、打開.bat文件編輯 2、輸入命令&#xff1a; mode co…

Java中的Stream是什么?

在Java中&#xff0c;Stream是一種用于處理集合&#xff08;Collections&#xff09;元素的抽象序列。它允許你在集合上進行不同類型的操作&#xff0c;比如篩選、映射、過濾和歸約等。Stream API引入了一種更函數式的編程風格&#xff0c;能夠簡化集合處理的過程。 Stream并不…

NLP項目實戰01之電影評論分類

介紹&#xff1a; 歡迎來到本篇文章&#xff01;在這里&#xff0c;我們將探討一個常見而重要的自然語言處理任務——文本分類。具體而言&#xff0c;我們將關注情感分析任務&#xff0c;即通過分析電影評論的情感來判斷評論是正面的、負面的。 展示&#xff1a; 訓練展示如下…

【基于LicheePi-4A的 人臉識別系統軟件設計】

參考:https://www.xrvm.cn/community/post/detail?spm=a2cl5.27438731.0.0.31d40dck0dckmg&id=4253195599836418048 1.前言 原先計劃做基于深度學習的炸藥抓取和智能填裝方法研究,但是后來發現板卡不支持pyrealsense2等多個依賴包。因此改變策略,做一款基于LicheePi…

Android Studio的筆記--三元表達式、布爾運算符、與() 或(||) 非(!)

[TOC](三元表達式、布爾運算符、與(&&) 或(||) 非(!)) 表達式 int x 1; int y 2;x < y 結果 true x > y 結果 false x < y 結果 false x > y 結果 true x y 結果 false x ! y 結果 true 布爾運算符 boolean boolean a true; boolean b false; 與…

【Python】列表乘積的計算時間

概述 使用以下三種模式測量了計算列表乘積所需的時間。 使用 for 語句傳遞list使用math模塊使用numpy 下面是實際運行的代碼。 import timestart time.time() A [1] * 100000000 ans 1 for a in A:ans * a print("list loop:", time.time() - start)import m…

前端面試提問(4)

1、手撕防抖與節流、樹與對象的轉換、遞歸調用&#xff0c;鏈表頭插法 1.1、防抖 防抖函數用于延遲執行某個函數&#xff0c;直到過了一定的間隔時間&#xff08;例如等待用戶停止輸入&#xff09;后再執行。 即后一次點擊事件發生時間距離一次點擊事件至少間隔一定時間。 …

笙默考試管理系統-MyExamTest----codemirror(49)

笙默考試管理系統-MyExamTest----codemirror&#xff08;49&#xff09; 目錄 笙默考試管理系統-MyExamTest----codemirror&#xff08;49&#xff09; 一、 笙默考試管理系統-MyExamTest----codemirror 二、 笙默考試管理系統-MyExamTest----codemirror 三、 笙默考試…

有哪些已經上線的vue商城項目?

前言 下面是一些商城的項目&#xff0c;需要練手的同學可以挑選一些來練&#xff0c;廢話少說&#xff0c;讓我們直接開始正題~~ 1、newbee-mall-vue3-app 是一個基于 Vue 3 和 TypeScript 的電商前端項目&#xff0c;它是 newbee-mall 項目的升級版。該項目包含了商品列表、…

內網環境下 - 安裝linux命令、搭建docker以及安裝鏡像

一 內網環境安裝docker 先在外網環境下載好docker二進制文件docker二進制文件下載&#xff0c;要下載對應硬件平臺的文件&#xff0c;否則不兼容 如下載linux平臺下的文件&#xff0c;直接訪問這里即可linux版本docker二進制文件 這里下載docker-24.0.5.tgz 將下載好的文件…