golang使用protobuf简易教程

golang使用protobuf简易教程

google公司发布的一套开源编码规则,基于二进制流的序列化传输,可以转换成多种编程语言,几乎涵盖了市面上所有的主流编程语言,当然也包括Go

1、安装protobuf

  1. 安装下载protoc,很多种安装方法,下载地址https://github.com/google/protobuf/releases
  2. 安装下载proto的go插件,命令是go get github.com/golang/protobuf/protoc-gen-go,也可以自己手动下载安装(如果使用go get则会自动生成protoc-gen-go的可执行文件)
  3. 将protoc-gen-go可执行文件路径加到PATH环境变量中,如果是go get安装是会在GOBIN路径下生成protoc-gen-go,执行export PATH=$PATH:$GOBIN(原因在于, protoc-gen-go可执行文件需要被protoc调用)
  4. 安装goprotobuf库(注意,protoc-gen-go只是一个插件,goprotobuf的其他功能比如marshal、unmarshal等功能还需要由protobuf库提供)go get github.com/golang/protobuf/proto
  5. 写example.proto文件以及.go文件测试。由于proto生成go文件的命令是protoc --go_out=./ example.proto

PS:

1.如果你是直接go get了gin、beego这种,一般就会顺便给你安装protobuf以及protoc-gen-go了。

2.如果你有protoc-gen-go代码,放到对应目录下后($GOPATH/src/github.com/golang/protobuf/),make install也可以手动安装protoc-gen-go

二、使用protobuf

1.example.proto示例文件

(具体语法请自行搜索)

syntax = "proto2"; 
//example.proto
package example;

// LD
message LD
{
    required uint32 ip = 1;         // LD的IP
}

// 集群
message Set
{
    required uint32 id                                     = 1;     // SET的id
    required string name                                   = 2;     // SET名字
    repeated LD ld_list                                    = 3;     // LD列表
}

注意required是必须要求的字段,optional是可选字段,同时注意, id=1, 后面的数字主要是保证其顺序与唯一性。

编译命令

protoc --go_out=./ example.proto

会生成文件example.pb.go

生成的代码如下:

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

/*
Package example is a generated protocol buffer package.

It is generated from these files:
    example.proto

It has these top-level messages:
    LD
    Set
*/
package example

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import 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.ProtoPackageIsVersion2 // please upgrade the proto package

// LD
type LD struct {
    Ip               *uint32 `protobuf:"varint,1,req,name=ip" json:"ip,omitempty"`
    XXX_unrecognized []byte  `json:"-"`
}

func (m *LD) Reset()                    { *m = LD{} }
func (m *LD) String() string            { return proto.CompactTextString(m) }
func (*LD) ProtoMessage()               {}
func (*LD) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

func (m *LD) GetIp() uint32 {
    if m != nil && m.Ip != nil {
        return *m.Ip
    }
    return 0
}

// 集群
type Set struct {
    Id               *uint32 `protobuf:"varint,1,req,name=id" json:"id,omitempty"`
    Name             *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"`
    LdList           []*LD   `protobuf:"bytes,3,rep,name=ld_list,json=ldList" json:"ld_list,omitempty"`
    XXX_unrecognized []byte  `json:"-"`
}

func (m *Set) Reset()                    { *m = Set{} }
func (m *Set) String() string            { return proto.CompactTextString(m) }
func (*Set) ProtoMessage()               {}
func (*Set) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }

func (m *Set) GetId() uint32 {
    if m != nil && m.Id != nil {
        return *m.Id
    }
    return 0
}

func (m *Set) GetName() string {
    if m != nil && m.Name != nil {
        return *m.Name
    }
    return ""
}

func (m *Set) GetLdList() []*LD {
    if m != nil {
        return m.LdList
    }
    return nil
}

func init() {
    proto.RegisterType((*LD)(nil), "example.LD")
    proto.RegisterType((*Set)(nil), "example.Set")
}

func init() { proto.RegisterFile("example.proto", fileDescriptor0) }

var fileDescriptor0 = []byte{
    // 126 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0xad, 0x48, 0xcc,
    0x2d, 0xc8, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0x95, 0x44, 0xb8,
    0x98, 0x7c, 0x5c, 0x84, 0xf8, 0xb8, 0x98, 0x32, 0x0b, 0x24, 0x18, 0x15, 0x98, 0x34, 0x78, 0x83,
    0x98, 0x32, 0x0b, 0x94, 0xfc, 0xb9, 0x98, 0x83, 0x53, 0x4b, 0xc0, 0xc2, 0x29, 0x70, 0xe1, 0x14,
    0x21, 0x21, 0x2e, 0x96, 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x26, 0x05, 0x26, 0x0d, 0xce, 0x20, 0x30,
    0x5b, 0x48, 0x85, 0x8b, 0x3d, 0x27, 0x25, 0x3e, 0x27, 0xb3, 0xb8, 0x44, 0x82, 0x59, 0x81, 0x59,
    0x83, 0xdb, 0x88, 0x5b, 0x0f, 0x66, 0x95, 0x8f, 0x4b, 0x10, 0x5b, 0x4e, 0x8a, 0x4f, 0x66, 0x71,
    0x09, 0x20, 0x00, 0x00, 0xff, 0xff, 0xce, 0x69, 0x42, 0x70, 0x7f, 0x00, 0x00, 0x00,
}

特别注意: 生成的文件中的package是example, 那么文件必须放在example文件夹下! 否则会报错: “can’t load package: package example

下面写一个测试程序:

// main.go
package main

import (
    "fmt"
    t "./example"
    "github.com/golang/protobuf/proto"
)

func main(){
    // 创建一个对象, 并填充字段, 可以使用proto中的类型函数来处理例如Int32(XXX)

    var hw t.Set
    var ld t.LD

    ld = t.LD {
        Ip: proto.Uint32(666),
    }

    hw = t.Set {
        Id: proto.Uint32(1),
        Name: proto.String("hello"),
        //LdList.append(ld),
    }

    // 对数据进行编码, 注意参数是message指针
    mData, err := proto.Marshal(&hw)

    if err != nil {
        fmt.Println("Error1: ", err)
        return
    }

    // 下面进行解码, 注意参数
    var umData t.Set
    err = proto.Unmarshal(mData, &umData)

    if err != nil {
        fmt.Println("Error2: ", err)
        return
    }

    // 输出结果
    fmt.Println(*umData.Id, "  ", *umData.Name, "  ", *ld.Ip)
}

目录结构

feiqianyousadeMacBook-Pro:protobuf yousa$ ls
apigw_agent.proto       common.proto            example.pb.go           main                protobuf-cpp-3.4.1.tar.gz   test.proto
apigw_master.proto      example             example.proto           main.go             test.pb.go
feiqianyousadeMacBook-Pro:protobuf yousa$ tree-d
-bash: tree-d: command not found
feiqianyousadeMacBook-Pro:protobuf yousa$ tree -d
.
└── example

1 directory
feiqianyousadeMacBook-Pro:protobuf yousa$ ls ./example
example.pb.go

编译&运行

go build main.go

./main

参考

go protobuf:https://github.com/golang/protobuf
proto文档:https://godoc.org/github.com/golang/protobuf/proto

猜你喜欢

转载自blog.csdn.net/qq_15437667/article/details/78425151