在Golang中使用Protobuf

2021-10-02 09:41:37 字數 4215 閱讀 7376

本教程使用proto3版本的protocol buffer語言,提供了乙個基本的在go程式中使用protocol buffer的介紹。通過建立乙個簡單的示例應用程式,向你展示如何

它不是乙個全面的在go中使用protocol buffer的指南,更詳細的參考資訊請檢視前面的兩個教程。

protobuf語言指南

protobuf生成go**指南

我們將要使用的示例是乙個非常簡單的「位址簿」應用程式,可以在檔案中讀取和寫入人員的聯絡人詳細資訊。位址簿中的每個人都有姓名,id,電子郵件位址和聯絡**號碼。

如何序列化和檢索這樣的結構化資料?有幾種方法可以解決這個問題:

protocol buffer是靈活,高效,自動化的解決方案,可以解決這個問題。使用protocol buffer,您可以編寫要儲存的資料結構的.proto描述。由此,protocol buffer編譯器會建立乙個類,該類使用有效的二進位制格式實現協議緩衝區資料的自動編碼和解析。生成的類會為構成protocol buffer的字段提供getter和setter,並負責將protocol buffer作為乙個單元讀取和寫入的細節。重要的是,protocol buffer格式支援隨著時間的推移擴充套件格式的想法,使得**仍然可以讀取使用舊格式編碼的資料。

示例是一組用於管理位址簿資料檔案的命令列應用程式,使用protocol buffer進行編碼。命令add_person_go向資料檔案新增新條目。命令list_people_go解析資料檔案並將資料列印到控制台。

要建立位址簿應用程式,您需要從.proto檔案開始。 .proto檔案中的定義很簡單:為要序列化的每個資料結構定義訊息,然後為訊息中的每個字段指定名稱和型別。在我們的示例中,定義訊息的.proto檔案是addressbook.proto。

.proto檔案以包宣告開頭,這有助於防止不同專案之間的命名衝突。

syntax = "proto3";

package tutorial;

import "google/protobuf/timestamp.proto";

在go中,protocol buffer的包名稱用作go包,除非您指定了go_package。即使你確實提供了go_package,你仍然應該在.proto檔案中定義乙個包名,以避免在protocol buffers命名空間和非go語言中發生名稱衝突。

接下來,是訊息定義。訊息只是包含一組型別欄位的聚合。許多標準的簡單資料型別都可用作字段型別,包括bool,int32,float,double和string。您還可以使用其他訊息型別作為字段型別,為訊息新增更多結構。

message person 

message phonenumber

repeated phonenumber phones = 4;

google.protobuf.timestamp last_updated = 5;

}// our address book file is just one of these.

message addressbook

在上面的示例中,person訊息包含phonenumber訊息,而addressbook訊息包含person訊息。您甚至可以定義巢狀在其他訊息中的訊息型別 -​​ 如您所見,phonenumber型別在person中定義。如果您希望其中乙個字段值的取值範圍是預定義的值列表中的值,還可以定義列舉型別 - 此處你要指定**號碼可以是mobilehomework之一。

每個元素上的「= 1」,「= 2」標記標識該字段在二進位制編碼中使用的唯一「標記」。標籤號1-15編碼時比更大編號少需要乙個位元組,因此作為優化,您可以決定將這些標籤用於常用或重複的元素,將標籤16和更高標籤留給不太常用的可選元素。重複欄位中的每個元素都需要重新編碼標記號,因此重複字段特別適合此優化。

如果未設定字段值,則使用預設值:數字型別為零,字串為空字串,bools為false。對於嵌入式訊息,預設值始終是訊息的「預設例項」或「原型」,其中沒有設定其欄位。呼叫訪問器以獲取尚未顯式設定的字段的值始終返回該字段的預設值。

如果乙個欄位是可重複的,該欄位可以重複任意次數(包括零)。重複值的順序將保留在protocol buffer中。將可重複字段視為變長陣列。

您將在protobuf語言指南中找到編寫.proto檔案的完整指南 - 包括所有可能的字段型別。不要去尋找類繼承類似的東西,protocol buffer不支援這些。

有了.proto後,你需要做的下一件事是生成你需要讀取和寫入addressbook(以及person和phonenumber)訊息所需的類(go中是結構體和結構體方法)。為此,你需要在.proto上執行protocol buffer譯器protoc:

請先確保已經安裝了編譯器protoc

protoc需要安裝外掛程式才能編譯生成go**,可以執行如下命令安裝外掛程式

現在執行編譯器,指定源目錄(應用程式的源**所在的位置 - 如果不提​​供值,則使用當前目錄),目標目錄(您希望生成的**在**;通常與$相同) src_dir),以及.proto的路徑。在這種情況下,你...:

protoc -i=$src_dir --go_out=$dst_dir $src_dir/addressbook.proto

​ 我們使用的示例go**中匯入編譯後的pb.go檔案的路徑是pb "github.com/protocolbuffers/protobuf/examples/tutorial"所以用protoc編譯時使用的目標路徑應該是

protoc --go_out=$gopath/src/github.com/protocolbuffers/protobuf/examples/tutorial ./addressbook.proto
$gopath/src/github.com/protocolbuffers/protobuf/examples/tutorial目錄需要提前建立好。

生成addressbook.pb.go提供以下有用型別:

可以閱讀更多有關「生成**」指南中生成的內容的詳細資訊,但在大多數情況下,您可以將這些視為完全普通的go型別。

下面是如何建立person例項的示例:

p := pb.person,

},}

使用protocl buffer目的是序列化你的結構化資料,以便可以在其他地方解析它。在go中,使用proto庫的marshal函式來序列化protocol buffer資料。指向訊息的結構體的指標實現了proto.message介面。呼叫proto.marshal會返回以其有線格式編碼的protocol buffer。例如,我們在add_person命令中使用此函式:

book := &pb.addressbook{}

// ...

// write the new address book back to disk.

out, err := proto.marshal(book)

if err != nil

if err := ioutil.writefile(fname, out, 0644); err != nil

要解析編碼訊息,請使用proto庫的unmarshal函式。呼叫它將buf中的資料解析為protocol buffer,並將結果放在結構體中。因此,要在list_people命令中解析檔案,我們使用:

// read the existing address book.

in, err := ioutil.readfile(fname)

if err != nil

book := &pb.addressbook{}

if err := proto.unmarshal(in, book); err != nil

Golang 在Golang中使用json

由於要開發乙個小型的web應用,而web應用大部分都會使用json作為資料傳輸的格式,所以有了這篇文章。包引用import 用於存放資料的結構體type mydata struct這裡需要注意的就是後面單引號中的內容。json item 這個的作用,就是name欄位在從結構體例項編碼到json資料格...

在 golang 中使用 Json

序列化物件將使用 encoding json 中的 marshal 函式。函式原型為 func marshal v inte ce byte,error 以下是官網給出的例子 package main import encoding json fmt os func main group color...

在 GoLang 中使用 jwt 進行認證

jwt 即 json web token,是用 json 形式安全傳輸資訊的方法。對 jwt 解碼,可以得到以下內容 jwt 可以設定過期時間,它的應用主要有 一般服務端生成 jwt 並返回給客戶端時,要放在 cookie裡,並且加上httponly的標記,意味著這個 cookie不能被 js獲取,...