protobuf與protoc-gen-go
來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。## 什麼是protobufProtobuf(Protocol Buffer)是google 的一種資料交換的格式,它獨立於語言,獨立於平台。google 提供了多種語言的實現:java、c#、c++、go 和 python,每一種實現都包含了相應語言的編譯器以及庫檔案。由於它是一種二進位的格式,比使用 xml 進行資料交換快許多。可以把它用於分布式應用之間的資料通訊或者異構環境下的資料交換。作為一種效率和相容性都很優秀的位元據傳輸格式,可以用於諸如網路傳輸、設定檔、資料存放區等諸多領域。(參考[連結](https://baike.baidu.com/item/protocol%20buffer/1664400?fr=aladdin))## 什麼是protocprotoc是protobuf檔案(.proto)的編譯器(參考[連結](https://github.com/google/protobuf)),可以藉助這個工具把 .proto 檔案轉譯成各種程式設計語言對應的源碼,包含資料類型定義、調用介面等。![protoc編譯過程](https://static.studygolang.com/180325/41775c725a2745e2e785f22bbd96a08c.png)通過查看protoc的源碼(參見[github庫](https://github.com/google/protobuf))可以知道,protoc在設計上把protobuf和不同的語言解耦了,底層用c++來實現protobuf結構的儲存,然後通過外掛程式的形式來產生不同語言的源碼。可以把protoc的編譯過程分成簡單的兩個步驟(如所示):1)解析.proto檔案,轉譯成protobuf的原生資料結構在記憶體中儲存;2)把protobuf相關的資料結構傳遞給相應語言的編譯外掛程式,由外掛程式負責根據接收到的protobuf原生結構渲染輸出特定語言的模板。源碼中(參見[github庫](https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/main.cc))包含的外掛程式有 csharp、java、js、objectivec、php、python、ruby等多種。## 什麼是protoc-gen-go protoc-gen-go是protobuf**編譯外掛程式**系列中的Go版本。從上一小節知道原生的protoc並不包含Go版本的外掛程式,不過可以在github上發現專門的程式碼程式庫(參見[github庫](github.com/golang/protobuf/protoc-gen-go))。由於protoc-gen-go是Go寫的,所以安裝它變得很簡單,只需要運行```go get -u github.com/golang/protobuf/protoc-gen-go```,便可以在$GOPATH/bin目錄下發現這個工具。至此,就可以通過下面的命令來使用protoc-gen-go了。```shellprotoc --go_out=output_directory input_directory/file.proto```其中"--go_out="表示產生Go檔案,protoc會自動尋找PATH(系統執行路徑)中的protoc-gen-go執行檔案。## protoc-gen-go的源碼![protoc-gen-go的源碼結構](https://static.studygolang.com/180325/fcfa10f6aa545027a3904783f0fd6ab5.png)按照Go的代碼風格,protoc-gen-go源碼主要包含六個包(package):* main包 * doc.go 主要是說明。 * link_grpc.go 顯式引用protoc-gen-go/grpc包,觸發grpc的init函數。 * main.go 代碼不到50行,初始化generator,並調用generator相應的方法輸出protobuf的Go語言檔案。* generator包 * generator.go 包含了大部分由protobuf原生結構到Go語言檔案的渲染方法,其中 `func (g *Generator) P(str ...interface{})` 這個方法會把渲染輸出到generator的output(generator匿名嵌套了bytes.Buffer,因此有Buffer的方法)。 * name_test.go 測試,主要包含generator中名稱相關方法的測試。* grpc包 * grpc.go 與generator相似,但是包含了很多產生grpc相關方法的方法,比如渲染轉譯protobuf中定義的rpc方法(在generator中不包含,其預設不轉譯service的定義)* descriptor 包含protobuf的描述檔案(.proto檔案及其對應的Go編譯檔案),其中proto檔案來自於proto庫(參見[這裡](https://github.com/google/protobuf/blob/master/src/google/protobuf/descriptor.proto))* plugin 包含plugin的描述檔案(.proto檔案及其對應的Go編譯檔案),其中proto檔案來自於proto庫,參見[這裡](https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/plugin.proto)## 結語從巴別塔的傳說(參見[這裡](https://baike.baidu.com/item/%E5%B7%B4%E5%88%AB%E5%A1%94/67557?fr=aladdin))可以知道,欲要構建大系統,個體之間的溝通規範很重要。protobuf的出現,為不同系統之間的串連提供了一種語言規範,只要遵循了這個規範,各個系統之間就是解耦的,非常適合近年來流行的微服務架構。如果吧protoc和protoc-gen-go看成兩個微服務,可以發現這兩個服務就是完全解耦的;兩者完全負責不同的功能,可以分別編碼、升級,串接這兩個服務的就是proto規範。300 次點擊 ∙ 1 贊