一、Protobuf簡介
Protocol Buffers(簡稱Protobuf)是Google開源的一種輕便高效的序列化數據結構的方法,由Google基於一種二進位協議實現,通過源代碼編譯器生成源代碼,具有良好的跨語言性。Protobuf可以生成Java、C++、Python等語言的源代碼,且序列化後的數據大小非常的小, 這種方式比XML快許多倍,同時也比JSON快。
二、Protobuf的使用
Protobuf結構體定義包含name,tag和type三個成員,其中name表示結構體成員名稱,tag表示用整形表示的序號,type表示結構體成員數據類型。
syntax = "proto3"; package example; message Person { string name = 1; int32 age = 2; string address = 3; }
在GO中使用Protobuf,首先需要安裝Protobuf。
go get -u github.com/golang/protobuf/proto
使用Protobuf需要創建.proto
文件並且定義好結構體,然後使用protoc
編譯器將.proto
文件編譯成目標語言的源代碼文件。
//編譯.proto文件 protoc --go_out=. person.proto
Protobuf提供了基本的Marshal和Unmarshal方法來進行序列化與反序列化操作。
package main import ( "github.com/golang/protobuf/proto" "example" ) func main() { // 創建結構體實例 p1 := &example.Person{ Name: "John", Age: 30, Address: "New York", } // 序列化 data, err := proto.Marshal(p1) if err != nil { log.Fatal("marshaling error: ", err) } // 反序列化 p2 := &example.Person{} err = proto.Unmarshal(data, p2) if err != nil { log.Fatal("unmarshaling error: ", err) } // p1 and p2 should contain the same data. fmt.Println("p1:", p1) fmt.Println("p2:", p2) }
三、Protobuf的高效性
1、數據大小
與JSON數據格式相比,Protobuf序列化後的數據更小,可以將數據傳輸的時間和成本的最小化。
//結構體定義 message Example { string field_one = 1; int32 field_two = 2; bool field_three = 3; } //JSON格式的數據大小 { "field_one": "Hello World!", "field_two": 12345, "field_three": true } //Protobuf格式的數據大小 data: 0a0c48656c6c6f20576f726c642109
2、效率
使用Protobuf進行序列化和反序列化操作的效率非常高。下面是一個比較序列化和反序列化操作的時間使用情況的代碼片段
p1 := &example.Person{ Name: "John", Age: 30, Address: "New York", } // Marshal the data and record the time it takes to do so. start := time.Now() data, err := proto.Marshal(p1) elapsed := time.Since(start) fmt.Printf("protobuf marshaling time elapsed: %s\n", elapsed)
在大規模數據的情況下,使用Protobuf所節省的時間和資源是非常可觀的。
四、總結
GO Protobuf實現消息序列化和反序列化的高效性使得它成為了一種高效且便於擴展性的數據交換方式。而且,由於Protobuf的良好跨語言特性,它可以輕鬆地在多種不同平台和語言之間交換數據。
完整代碼示例
syntax = "proto3"; package example; message Person { string name = 1; int32 age = 2; string address = 3; } package main import ( "fmt" "github.com/golang/protobuf/proto" "log" "time" "example" ) func main() { // test protobuf encoding and decoding for example.Person p1 := &example.Person{ Name: "John", Age: 30, Address: "New York", } // Marshal the data. start := time.Now() data, err := proto.Marshal(p1) elapsed := time.Since(start) fmt.Printf("protobuf marshaling time elapsed: %s\n", elapsed) if err != nil { log.Fatal("marshaling error: ", err) } // Display the raw protobuf bytes. fmt.Printf("raw Protobuf bytes: %q\n", data) // Unmarshal the data back into a person struct. p2 := &example.Person{} start = time.Now() err = proto.Unmarshal(data, p2) elapsed = time.Since(start) fmt.Printf("protobuf unmarshaling time elapsed: %s\n", elapsed) if err != nil { log.Fatal("unmarshaling error: ", err) } // Display the original and unmarshaled structs. fmt.Println("Original struct :", p1) fmt.Println("Unmarshaled struct:", p2) }
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/270761.html