protoBuf-go學習筆記
protoBuf官方簡介
protocol buffers 是一種語言無關、平臺無關、可擴展的序列化結構數據的方法
它可用於(數據)通信協議、數據存儲等。
Protocol Buffers 是一種靈活,高效,自動化機制的結構數據序列化方法
可類比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更爲簡單。
你可以定義數據的結構,然後使用特殊生成的源代碼
輕鬆的在各種數據流中使用各種語言進行編寫和讀取結構數據。
你甚至可以更新數據結構,而不破壞由舊數據結構編譯的已部署程序。
protobuf通過定義包含類型結構序列化信息的文件(.proto文件),來編譯生成不同語言平臺的高效序列化程序代碼
下載protoBuf編譯器
根據不同系統下載不同protoc編譯器,在windows下下載windows後綴的
protoc-3.12.0-rc-1-winxxx.zip
解壓後得到的目錄中,bin目錄中的protoc.exe就是編譯protoc代碼命令
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/5/5 1:24 bin
d----- 2020/5/5 1:24 include
-a---- 2020/5/5 1:24 724 readme.txt
把protoc.exe複製到GOPATH/bin目錄下
安裝go專屬plugin
protobuf編譯器有支持golang需要安裝protoc-gen-go這個go插件
通過下載源碼編譯後,把編譯出的exe重命名爲protoc-gen-go.exe放到GOPATH/bin下
github.com/golang/protobuf
cd protoc-gen-go
go build main.go
編譯proto到go代碼
在確保有將GOPATH/bin加入環境變量後,即可在任意目錄使用protoc命令
protoc --go_out=. --proto_path=. *.proto
其中,go_out指定編譯的go代碼輸出路徑,proto_path指定查找proto文件所在的根目錄,最後一個參數是要編譯的proto文件名
最終舊生成了代碼文件xxx.pb.go
proto包名
如果編譯出現警告
Missing 'go_package' option in "test.proto"
這是因爲默認.proto文件中的包聲明生成源代碼時作爲Go的包名,包名中的. 在Go包名中會轉換爲_。
比如proto包名a.b將會變爲Go包名a_b,所以一般通過option go_package指令來指定Go包名
比如如下代碼指定了go包名爲a.b(不管是否定義了proto包名)
option go_package = "a.b";
syntax聲明
一般在proto文件開頭使用syntax聲明proto版本,默認是proto2
比如
syntax = "proto3";
導入包
通過import語句導入proto包,比如
import "google/protobuf/struct.proto"
定義message
protobuf中使用關鍵字message定義結構,並且結構中可以嵌套定義結構,比如
message A {}
message B {
message C {
}
}
內嵌類型最終會編譯爲以外部類型名稱_名稱作爲類型名稱的結構體,比如此處,生成的結構體有3個,分別是
type A struct {...}
type B struct {...}
type B_C struct {...}
定義字段
基本定義語法如下,其中type是類型,name是字段名稱,num是數據編號
當反序列化時,會把對應數據編號對應的數據填充到對應字段
對於type,如果是message類型,在編譯爲語言代碼時會被轉化爲對應的指針類型
type name = num
- 基本類型
message A { string name = 1; }
- message類型
message B { string name = 1; } message A { B b = 1; }
- map
message A { map<string,int> pic = 1; }
- 枚舉
枚舉類型會被編譯爲整型的替代類型,枚舉值會變爲const變量,以類型名_枚舉量名作爲名稱
與message類似,枚舉也可以嵌套在類型中,最終會編譯爲以外部類型名稱_枚舉名稱作爲類型名稱
比較獨特的,枚舉枚舉中枚舉量的數值就是他們編譯後代碼中常量的初始化數值,第一個枚舉量的數據編號必須是0message A{ enum Color{ RED = 0; BLACK = 1; } Color c = 1; } enum Day{ ONE = 0; TWO = 1; }
- repeated類型(數組)
通過在類型前加上關鍵字repeated代表其爲數組類型,該字段序列化可能出現0次或多次,比如
最終生成message B{} message A{ repeated B bs= 1; }
type B struct {...} type A struct { ... Bs []*B ... }
定義服務
proto支持通過service與rpc關鍵字分別定義rpc服務和rpc方法,proto默認不會生成rpc代碼,需要結合對應的rpc插件(grpc、twirp等)編譯纔會生成
比如如下代碼,定義了一個service,提供一個search的rpc調用方法,接收一個Request類型的參數,返回Response類型的結果
message Request{}
message Response{}
service Search{
rpc search(Request) returns(Response);
}
golang使用proto
- 依賴
google.golang.org/protobuf/
- 導入包
google.golang.org/protobuf/proto
- proto.Marshal(interface{} obj) 方法將對象序列化爲字節數組
- proto.Unmarshal([]byte bs, interface{} obj)方法將字節數組反序列化爲對象
//A is message a := A{} bis, _ := proto.Marshal(&a) fmt.Printf("%v\n", bis) var r A proto.Unmarshal(bis, &r) fmt.Printf("%v\n", r)