• 理解Golang组件protobuf



     

    什么是protobuf#

    protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。

    protobuf与json区别#

    JSON与Protobuf都可以用来信息交换,JSON是一种简单的消息格式,以文本方式传输,而Protobuf是以二进制方式进行传输,相较于JSON消息体积会有明显的缩小,所以传输速度也比JSON快。除此之外,Protobuf不仅仅是一种用于交换的消息格式,还是用于定义交换消息的规则和工具,目前基本支持所有的主流语言。

    使用#

    先通过命令行进行安装

    Copy
    go get -u github.com/golang/protobuf/protoc-gen-go
    

    再创建一个名为test.proto的文件,键入以下内容

    Copy
    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文件。

    Copy
    protoc --go_out=./ test.proto
    

    可以看到在根目录中生成了一个名为test.pb.go的文件

    Copy
    // 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文件中进行序列化测试

    Copy
    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

  • 相关阅读:
    mysql 执行计划 explain
    深度学习论文翻译解析(二十):YOLOv4: Optimal Speed and Accuracy of Object Detection
    卷积神经网络学习笔记——轻量化网络MobileNet系列(V1,V2,V3)
    OpenCV计算机视觉学习(13)——图像特征点检测(Harris角点检测,sift算法)
    人工智能必备数学基础:概率论与数理统计(2)
    人工智能必备数学基础:概率论与数理统计(1)
    深度学习论文翻译解析(十九):Searching for MobileNetV3
    深度学习论文翻译解析(十八):MobileNetV2: Inverted Residuals and Linear Bottlenecks
    深度学习论文翻译解析(十七):MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications
    卷积神经网络学*笔记——SENet
  • 原文地址:https://www.cnblogs.com/cheyunhua/p/16205657.html
Copyright © 2020-2023  润新知