go語言學習-------Go語言中使用 protobuf
protobuf以前只支援C++, Python和Java等語言, Go語言出來後, 作為親兒子, 那有不支援的道理呢? github地址: go protobuf.
1. 安裝protobuf
<1> 去這兒下載protobuf git clone https://github.com/google/protobuf.git 執行autogen.sh安裝獲取protobuf編譯器protoc編譯器,也可以按照下面的步驟安裝:
./configure make make install protoc -h<2> 獲取並安裝proto-gen-go,
go get github.com/golang/protobuf/protoc-gen-go
, 這條命令會生成protoc-gen-go的可執行檔案<3> 注意將protoc-gen-go可執行檔案路徑加到PATH環境變數中, 或者將protoc-gen-go可執行檔案放到類似於/usr/local/bin這樣的路徑下, 只要在PATH路徑下就OK. 原因在於, protoc-gen-go可執行檔案需要被protoc呼叫.
<4> 獲取 goprotobuf 提供的支援庫,包含諸如marshal、unmarshal等功能, 使用命令
go get github.com/golang/protobuf/proto
.<5> 寫一個test.proto檔案,執行protoc test.proto --go_out=.生成go語言的程式碼,如果提示libprotoc.so找不到,需要把/usr/local/lib 新增到LD_LIBRARY_PATH環境變數中。
2. 使用protobuf
首先我們需要寫一個test.proto檔案, 在這個檔案中可以定義需要的結構, 例如列舉型, 結構體等等. 那麼首先我自己定義了一個結構如下所示,
// test.protopackage test;
message myMsg
{
required int32 id =1;// ID
required string str =2;// str
optional int32 opt =3;//optional field}
注意required是必須要求的欄位, optional是可選欄位. 同時注意, id=1, 後面的數字僅僅是一個unique標誌而已, 保證唯一性就OK!
然後使用protoc test.proto --go_out=. 編譯這個檔案, 生成的檔名稱為test.pb.go檔案! 如果這個路徑下有多個檔案需要編譯, 那麼執行protoc --go_out=. *.proto就可以. 注意--go_out=後面的引數是生成的檔案的路徑, 本文生成的檔案在'.'當前路徑下.
生成的程式碼如下:
// Code generated by protoc-gen-go.// source: 1.proto// DO NOT EDIT!/*
Package test is a generated protocol buffer package.
It is generated from these files:
1.proto
It has these top-level messages:
MyMsg
*/package test
import proto "github.com/golang/protobuf/proto"import math "math"// Reference imports to suppress errors if they are not otherwise used.var _ = proto.Marshalvar _ = math.Inf
type MyMsgstruct{Id*int32 `protobuf:"varint,1,req,name=id" json:"id,omitempty" bson:"id,omitempty"`Str*string`protobuf:"bytes,2,req,name=str" json:"str,omitempty" bson:"str,omitempty"`Opt*int32 `protobuf:"varint,3,opt,name=opt" json:"opt,omitempty" bson:"opt,omitempty"`
XXX_unrecognized []byte`json:"-"`}
func (m *MyMsg)Reset(){*m =MyMsg{}}
func (m *MyMsg)String()string{return proto.CompactTextString(m)}
func (*MyMsg)ProtoMessage(){}
func (m *MyMsg)GetId() int32 {if m !=nil&& m.Id!=nil{return*m.Id}return0}
func (m *MyMsg)GetStr()string{if m !=nil&& m.Str!=nil{return*m.Str}return""}
func (m *MyMsg)GetOpt() int32 {if m !=nil&& m.Opt!=nil{return*m.Opt}return0}
func init(){}
特別注意: 生成的檔案中的package是test, 那麼檔案必須放在test資料夾下! 否則會報錯: "can't load package: package test: found packages test (test.pb.go) and main (main.go)"
下面寫一個測試程式:
// main.gopackage main
import("fmt"
t "./test""github.com/golang/protobuf/proto")
func main(){// 建立一個物件, 並填充欄位, 可以使用proto中的型別函式來處理例如Int32(XXX)
hw := t.MyMsg{Id: proto.Int32(1),Str: proto.String("iyviasbjasdv"),Opt: proto.Int32(2),}// 對資料進行編碼, 注意引數是message指標
mData, err := proto.Marshal(&hw)if err !=nil{
fmt.Println("Error1: ", err)return}// 下面進行解碼, 注意引數var umData t.MyMsg
err = proto.Unmarshal(mData,&umData)if err !=nil{
fmt.Println("Error2: ", err)return}// 輸出結果
fmt.Println(*umData.Id," ",*umData.Str," ",*umData.Opt)}
簡單的用法完畢, 然後我們就能愉快地使用protobuf定義自己的訊息協議了, 贊!
只有protobuf中的編解碼原理, 有時間再去深究了~~~