goprotobuf基本使用

Rhino(犀牛) · · 5744 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

如果你对Google Protocol Buffer不了解,可以先看下我这篇文章里收集的中文资料:关于Google Protocol Buffer的中文资料
源码地址:https://code.google.com/p/goprotobuf/
详细的介绍:https://code.google.com/p/goprotobuf/source/browse/README
介绍:
This software has two parts: a ‘protocol compiler plugin’ that generates Go source files that, once compiled, can access and manage protocol buffers; and a library that implements run-time support for encoding (marshaling), decoding (unmarshaling), and accessing protocol buffers.
大意:
该软件包含两部分:protoc-gen-go:一旦使用’协议编译器插件‘编译,会生成一些go的源码文件,可以访问和管理protocol buffers;proto:是一个实现运行时支持,为编码(编组),解码(解编)的库,和访问protocol buffers。
简单的说,protoc-gen-go是一个编译器,用来把 *.proto协议文件,编译生成 *.pb.go文件。再接下来的例子,我们会介绍如何使用它。
而proto需要包含到我们的软件里,去将消息编码为二进制数据,或者将二进制数据还原为消息对象。
源码下载:
go get -u code.google.com/p/goprotobuf/{proto,protoc-gen-go}
或者直接下载源码到自己的项目里:
hg clone https://code.google.com/p/goprotobuf/
如下图:

编译:

编译成功后,我们会发现bin目录下,会生成protoc-gen-go文件,以及pkg目录下会生成对应的库文件。
接下来,我们编写测试一个例子:
首先,编写test.proto,内容如下:

package example;

enum FOO { X = 17; };

message Test {
required string label = 1;
optional int32 type = 2 [default=77];
repeated int64 reps = 3;
optional group OptionalGroup = 4 {
required string RequiredField = 5;
}
}

接着,编写Makefile文件,用于生成*.pb.go文件,内容如下:

include ../code.google.com/p/goprotobuf/Make.protobuf

all: regenerate

regenerate:
rm -f test.pb.go
make test.pb.go

# The following rules are just aids to development. Not needed for typical testing.

diff: regenerate
hg diff test.pb.go

restore:
cp test.pb.go.golden test.pb.go

preserve:
cp test.pb.go test.pb.go.golden

终端下,make以后,我们会看到生成对应的test.pb.go文件,内容如下:

// Code generated by protoc-gen-go.
// source: test.proto
// DO NOT EDIT!

package example

import proto "code.google.com/p/goprotobuf/proto"
import json "encoding/json"
import math "math"

// Reference proto, json, and math imports to suppress error if they are not otherwise used.
var _ = proto.Marshal
var _ = &json.SyntaxError{}
var _ = math.Inf

type FOO int32

const (
FOO_X FOO = 17
)

var FOO_name = map[int32]string{
17: "X",
}
var FOO_value = map[string]int32{
"X": 17,
}

func (x FOO) Enum() *FOO {
p := new(FOO)
*p = x
return p
}
func (x FOO) String() string {
return proto.EnumName(FOO_name, int32(x))
}
func (x FOO) MarshalJSON() ([]byte, error) {
return json.Marshal(x.String())
}
func (x *FOO) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(FOO_value, data, "FOO")
if err != nil {
return err
}
*x = FOO(value)
return nil
}

type Test struct {
Label *string protobuf:"bytes,1,req,name=label" json:"label,omitempty"
Type *int32 protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"
Reps []int64 protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"
Optionalgroup *Test_OptionalGroup protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"
XXX_unrecognized []byte json:"-"
}

func (this *Test) Reset() { *this = Test{} }
func (this *Test) String() string { return proto.CompactTextString(this) }
func (*Test) ProtoMessage() {}

const Default_Test_Type int32 = 77

func (this *Test) GetLabel() string {
if this != nil && this.Label != nil {
return *this.Label
}
return ""
}

func (this *Test) GetType() int32 {
if this != nil && this.Type != nil {
return *this.Type
}
return Default_Test_Type
}

func (this *Test) GetOptionalgroup() *Test_OptionalGroup {
if this != nil {
return this.Optionalgroup
}
return nil
}

type Test_OptionalGroup struct {
RequiredField *string protobuf:"bytes,5,req" json:"RequiredField,omitempty"
}

func (this *Test_OptionalGroup) Reset() { *this = Test_OptionalGroup{} }

func (this *Test_OptionalGroup) GetRequiredField() string {
if this != nil && this.RequiredField != nil {
return *this.RequiredField
}
return ""
}

func init() {
proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
}

最后,编写测试代码如下:

package main

import (
"log"

"code.google.com/p/goprotobuf/proto"
"example"
"fmt"
)

func main() {
test := &example.Test{
Label: proto.String("hello"),
Type: proto.Int32(17),
Optionalgroup: &example.Test_OptionalGroup{
RequiredField: proto.String("good bye"),
},
}
// print test by string.
fmt.Println(test.String())
data, err := proto.Marshal(test)
if err != nil {
log.Fatal("marshaling error: ", err)
}
// print data
fmt.Println(data)
newTest := &example.Test{}
err = proto.Unmarshal(data, newTest)
if err != nil {
log.Fatal("unmarshaling error: ", err)
}
// Now test and newTest contain the same data.
if test.GetLabel() != newTest.GetLabel() {
log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
}
// etc.
}

编译运行,结果如下:

这里只是简单介绍并编写了个测试例子,许多细节并没有介绍,以后有机会再跟大家分享。


有疑问加站长微信联系(非本文作者)

本文来自:Rhino 的博客

感谢作者:Rhino(犀牛)

查看原文:goprotobuf基本使用

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

5744 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传