什麼是protobuf protocol buffers 是一種語言無關、平臺無關、可擴展的序列化結構數據的方法,它可用於(數據)通信協議、數據存儲等。是一種靈活,高效,自動化機制的結構數據序列化方法-可類比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更為簡單。 p ...
什麼是protobuf
protocol buffers 是一種語言無關、平臺無關、可擴展的序列化結構數據的方法,它可用於(數據)通信協議、數據存儲等。是一種靈活,高效,自動化機制的結構數據序列化方法-可類比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更為簡單。
protobuf與json區別
JSON與Protobuf都可以用來信息交換,JSON是一種簡單的消息格式,以文本方式傳輸,而Protobuf是以二進位方式進行傳輸,相較於JSON消息體積會有明顯的縮小,所以傳輸速度也比JSON快。除此之外,Protobuf不僅僅是一種用於交換的消息格式,還是用於定義交換消息的規則和工具,目前基本支持所有的主流語言。
使用
先通過命令行進行安裝
go get -u github.com/golang/protobuf/protoc-gen-go
再創建一個名為test.proto
的文件,鍵入以下內容
syntax = "proto3";
package main;
message Test {
string label = 1;
int32 type = 2;
repeated int64 reps = 3;
}
我們以proto3為例,創建一個叫Test的message,設置三個屬性,label、type和int64,repeated對應生成的Go語言變數類型為切片。下麵在命令行執行protoc來生成Go文件。
protoc --go_out=./ test.proto
可以看到在根目錄中生成了一個名為test.pb.go
的文件
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: test.proto
package main
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Test struct {
Label string `protobuf:"bytes,1,opt,name=label,proto3" json:"label,omitempty"`
Type int32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"`
Reps []int64 `protobuf:"varint,3,rep,packed,name=reps,proto3" json:"reps,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Test) Reset() { *m = Test{} }
func (m *Test) String() string { return proto.CompactTextString(m) }
func (*Test) ProtoMessage() {}
func (*Test) Descriptor() ([]byte, []int) {
return fileDescriptor_c161fcfdc0c3ff1e, []int{0}
}
func (m *Test) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Test.Unmarshal(m, b)
}
func (m *Test) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Test.Marshal(b, m, deterministic)
}
func (m *Test) XXX_Merge(src proto.Message) {
xxx_messageInfo_Test.Merge(m, src)
}
func (m *Test) XXX_Size() int {
return xxx_messageInfo_Test.Size(m)
}
func (m *Test) XXX_DiscardUnknown() {
xxx_messageInfo_Test.DiscardUnknown(m)
}
var xxx_messageInfo_Test proto.InternalMessageInfo
func (m *Test) GetLabel() string {
if m != nil {
return m.Label
}
return ""
}
func (m *Test) GetType() int32 {
if m != nil {
return m.Type
}
return 0
}
func (m *Test) GetReps() []int64 {
if m != nil {
return m.Reps
}
return nil
}
func init() {
proto.RegisterType((*Test)(nil), "main.Test")
}
func init() {
proto.RegisterFile("test.proto", fileDescriptor_c161fcfdc0c3ff1e)
}
var fileDescriptor_c161fcfdc0c3ff1e = []byte{
// 104 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e,
0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xc9, 0x4d, 0xcc, 0xcc, 0x53, 0x72, 0xe1, 0x62,
0x09, 0x49, 0x2d, 0x2e, 0x11, 0x12, 0xe1, 0x62, 0xcd, 0x49, 0x4c, 0x4a, 0xcd, 0x91, 0x60, 0x54,
0x60, 0xd4, 0xe0, 0x0c, 0x82, 0x70, 0x84, 0x84, 0xb8, 0x58, 0x4a, 0x2a, 0x0b, 0x52, 0x25, 0x98,
0x14, 0x18, 0x35, 0x58, 0x83, 0xc0, 0x6c, 0x90, 0x58, 0x51, 0x6a, 0x41, 0xb1, 0x04, 0xb3, 0x02,
0xb3, 0x06, 0x73, 0x10, 0x98, 0x9d, 0xc4, 0x06, 0x36, 0xd2, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff,
0x7b, 0xa2, 0xc6, 0x01, 0x60, 0x00, 0x00, 0x00,
}
我們在main文件中進行序列化測試
package main
import (
"fmt"
"github.com/golang/protobuf/proto"
)
func main() {
test := &Test{
Label: "a",
Type: 32,
Reps: []int64{10, 11},
}
resp, err := proto.Marshal(test)
if err != nil {
fmt.Println(err)
}
fmt.Println(resp)
}
protobuf生成了一個名為Test的結構體,其中有三個成員屬性,正好與test.proto文件對應,執行poroto.Marshal
方法可以對結構體進行序列化,後續就可以藉助RPC或HTTP的載體進行傳輸。
Golang組件示例代碼倉庫,歡迎star