温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

golang中Protobuf如何使用

发布时间:2021-07-06 15:42:29 阅读:185 作者:Leah 栏目:编程语言
GO开发者专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章给大家介绍golang中Protobuf如何使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

   protobuf是一种高效的数据传输格式(Google's data interchange format),且与语言无关,protobuf和json是基于http服务中最常见的两种数据格式。今天来学习基于golang的protobuf相关内容。

要想使用protobuf,需要4步:

  1. 下载安装google protocol buffer 编译器:https://github.com/google/protobuf/releases/tag/v3.5.1

  2. 下载安装golang protobuf plugin:https://github.com/golang/protobuf
    使用go tools安装:go get -u github.com/golang/protobuf/protoc-gen-go

  3. 按照protobuf 语法规则编写.proto文件

  4. 将proto文件编译成golang代码模型
    protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/addressbook.proto
    -IPATH, --proto_path=PATH 指定import路径
    --go_out 指定生成go代码路径(同理--java_out是指定java生成路径)  


下面以一个实际例子来说明:
addressbook.proto

syntax = "proto3";
package test.protobuf.tutorial;
message Person{
    string name  = 1;//姓名
    int32  id    = 2;//id编号
    string email = 3;//邮箱
    enum PhoneType { //枚举类型(电话类型)
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
    }
    message PhoneNumber{
        string    number = 1;
        PhoneType type   = 2;
    }
    repeated PhoneNumber phones = 4//repeated可理解为动态数组
}

// Our address book file is just one of these.
message AddressBook {
    repeated Person people = 1;
}

编译生成go文件。protoc会调用protoc-go-gen来生成go文件
.
├── addressbook.proto
└── src
└── addressbook.pb.go
protoc --go_out=./src addressbook.proto

addressbook.pb.go

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

/*
Package test_protobuf_tutorial is a generated protocol buffer package.

It is generated from these files:
    addressbook.proto

It has these top-level messages:
    Person
    AddressBook
*/
package test_protobuf_tutorial

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

type Person_PhoneType int32

const (
    Person_MOBILE Person_PhoneType = 0
    Person_HOME   Person_PhoneType = 1
    Person_WORK   Person_PhoneType = 2
)

var Person_PhoneType_name = map[int32]string{
    0"MOBILE",
    1"HOME",
    2"WORK",
}
var Person_PhoneType_value = map[string]int32{
    "MOBILE"0,
    "HOME":   1,
    "WORK":   2,
}

func (x Person_PhoneType) String() string {
    return proto.EnumName(Person_PhoneType_name, int32(x))
}
func (Person_PhoneType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{00} }

type Person struct {
    Name   string                `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
    Id     int32                 `protobuf:"varint,2,opt,name=id" json:"id,omitempty"`
    Email  string                `protobuf:"bytes,3,opt,name=email" json:"email,omitempty"`
    Phones []*Person_PhoneNumber `protobuf:"bytes,4,rep,name=phones" json:"phones,omitempty"`
}

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

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

func (m *Person) GetId() int32 {
    if m != nil {
        return m.Id
    }
    return 0
}

func (m *Person) GetEmail() string {
    if m != nil {
        return m.Email
    }
    return ""
}

func (m *Person) GetPhones() []*Person_PhoneNumber {
    if m != nil {
        return m.Phones
    }
    return nil
}

type Person_PhoneNumber struct {
    Number string           `protobuf:"bytes,1,opt,name=number" json:"number,omitempty"`
    Type   Person_PhoneType `protobuf:"varint,2,opt,name=type,enum=test.protobuf.tutorial.Person_PhoneType" json:"type,omitempty"`
}

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

func (m *Person_PhoneNumber) GetNumber() string {
    if m != nil {
        return m.Number
    }
    return ""
}

func (m *Person_PhoneNumber) GetType() Person_PhoneType {
    if m != nil {
        return m.Type
    }
    return Person_MOBILE
}

// Our address book file is just one of these.
type AddressBook struct {
    People []*Person `protobuf:"bytes,1,rep,name=people" json:"people,omitempty"`
}

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

func (m *AddressBook) GetPeople() []*Person {
    if m != nil {
        return m.People
    }
    return nil
}

func init() {
    proto.RegisterType((*Person)(nil), "test.protobuf.tutorial.Person")
    proto.RegisterType((*Person_PhoneNumber)(nil), "test.protobuf.tutorial.Person.PhoneNumber")
    proto.RegisterType((*AddressBook)(nil), "test.protobuf.tutorial.AddressBook")
    proto.RegisterEnum("test.protobuf.tutorial.Person_PhoneType", Person_PhoneType_name, Person_PhoneType_value)
}

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

var fileDescriptor0 = []byte{
    // 265 bytes of a gzipped FileDescriptorProto
    0x1f0x8b0x080x000x000x000x000x000x020xff0x8c0x900xc10x4b0xbc0x50,
    0x100xc70x7f0xba0xee0xe30xb70x230x2c0x360xc40x220x1d0x420x3c0x49,
    0x810x870x0d0x3a0x750x490x100x8a0xda0x5c0x1e0x410x670xcd0x890x64,
    0xd50x790xe80xf30xb00xff0x490x7f0x6e0xf80x940xe80x100xd10xed0x3b,
    0xc30x670xf80xcc0x0c0x9c0xe40x650xd90x510xdf0x170xcc0x870x580x75,
    0xac0x190x370x9a0x7a0x3d0xe50x620x780x8b0xf50xa00xb90xab0xf20x3a,
    0xfc0xb00x410xec0xa90xeb0xb90x450x040xa70xcd0x1b0xf20xad0xc00x8a,
    0x560xd20x640x5c0x830x5d0x950xbe0x1d0x580xd10x520xda0x550x890xa7,
    0xb00xa40x260xaf0x6a0x7f0x610xa00xa90xc00x040x840x7a0xe70x960x7a,
    0xdf0x090x160x910xbb0xbd0x880x7f0xb60xc50x930x290xde0x8f0xf00xd3,
    0xd00x140xd40xc90x790xf20xec0x150xdc0x6f0x6d0xdc0x800x680x4d0x9a,
    0xd70x990x2b0xbc0x010x470x1f0x150x990x950xd60xdb0xe80x2f0xa20xe7,
    0xa30x220x690xa60xc20x4b0x580x7d0xb50x100x400xec0xb20xe40xfe0x31,
    0xf50xfe0xe10x7f0x700xee0xb20x5d0xea0x590x630x7a0xc90xe40x830x67,
    0x870x290xb80xb70xd30x1f0x130xe60x030x5e0x830x500xc40xaa0x1e0x1f,
    0x340x1e0x790xfe0xbb0x5b0xce0x740x210x0c0x710xf50x190x000x000xff,
    0xff0x380xba0x260x8c0x950x010x000x00,
}

ok,生成模型代码后,我们就可以使用protobuf协议来对数据进行编解码了

 //将数据编码成protobuf 二进制格式--Writing a Message
 func EncodeAddressBook (book *pb.AddressBook)(out []byte, err error) {
    // Write the new address book back to disk.
    out, err = proto.Marshal(book)
    if err != nil {
        log.Println("Failed to encode address book:", err)
        return nil,err
    }
    if err := ioutil.WriteFile("addressbook_proto.data", out, 0644); err != nil {
        log.Fatalln("Failed to write address book:", err)
        return nil,err
    }
    fmt.Println("[Debug]: ", out)
    return
}
  //将二进制数据解码为golang 数据结构 --Reading a Message
 func DecodeAddressBook(in []byte) (book *pb.AddressBook, err error){
    // Read the existing address book.
    book = &pb.AddressBook{}
    if err := proto.Unmarshal(in, book); err != nil {
        log.Println("Failed to parse address book:", err)
        return nil,err
    }
    return
}

关于golang中Protobuf如何使用就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×