zoukankan      html  css  js  c++  java
  • 理解Golang组件protobuf

    什么是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

    https://github.com/EnochZg/golang-examples

  • 相关阅读:
    python的复制,深拷贝和浅拷贝的区别(转)
    linux下ffmpeg安装(转)
    Linux下的tar压缩解压缩命令详解(转)
    centos7安装python-pip(转)
    爬山算法和模拟退火算法简介
    协方差、协方差矩阵定义与计算
    七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)
    Canny边缘检测算法原理及其VC实现详解(二)
    Canny边缘检测算法原理及其VC实现详解(一)
    perforce变量配置与使用
  • 原文地址:https://www.cnblogs.com/pingyeaa/p/12577966.html
Copyright © 2011-2022 走看看