Protocol Buffers(protobuf)是一种由Google开发的轻量级、高效的数据序列化格式。它设计的目的是为了在不同系统之间进行数据交换,同时保持数据的结构化和高效传输。以下是一些关键特点:
- 二进制格式: Protobuf 使用二进制格式来序列化数据,相比于一些文本格式(如JSON和XML),二进制格式更加紧凑,传输效率更高。
- 结构化数据: Protobuf 使用消息定义数据结构,类似于在编程语言中定义类或结构体。每个消息中包含一组字段,每个字段都有一个唯一的标识符和数据类型。
- 可扩展性: Protobuf 支持向已定义的消息中添加新的字段,而不破坏现有代码。这使得系统可以在不中断现有功能的情况下演化。
跨语言支持: Protobuf 提供了多种语言的实现,包括但不限于C++, Java, Python等。这使得在不同编程语言中使用相同的数据结构变得更加容易。
高效性能: 由于采用二进制格式和紧凑的数据结构,Protobuf 在序列化和- 反序列化时具有较高的性能。 - 代码生成: 使用 Protobuf 需要定义消息的结构,然后使用编译器生成相应语言的代码。这些生成的代码用于序列化和反序列化消息。
mac 安装protobuf
brew install grpc
brew install protobuf
brew install protoc-gen-go
brew install protoc-gen-go-grpc
一个简单的 Protobuf 消息定义如下(使用 Protobuf 3 语法):
syntax = "proto3";
option go_package = "/pb";
package grpc.gateway.demo.proto.examplepb;
message Person{
int32 id = 1;
string name = 2;
string email = 3;
float salary = 4;
bool sex = 5;
}
这里有一个重点
序号15之前都是占用1个字节
15后占用两个
所以性能上 15之前尽量放一些热点属性
使用protoc 执行编译
protoc -I=. --go_out=. ./proto/base/base.proto
结果文件
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc v4.25.2
// source: proto/base/base.proto
package pb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Person struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
Salary float32 `protobuf:"fixed32,4,opt,name=salary,proto3" json:"salary,omitempty"`
Sex bool `protobuf:"varint,5,opt,name=sex,proto3" json:"sex,omitempty"`
}
func (x *Person) Reset() {
*x = Person{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_base_base_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Person) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Person) ProtoMessage() {}
func (x *Person) ProtoReflect() protoreflect.Message {
mi := &file_proto_base_base_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Person.ProtoReflect.Descriptor instead.
func (*Person) Descriptor() ([]byte, []int) {
return file_proto_base_base_proto_rawDescGZIP(), []int{0}
}
func (x *Person) GetId() int32 {
if x != nil {
return x.Id
}
return 0
}
func (x *Person) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Person) GetEmail() string {
if x != nil {
return x.Email
}
return ""
}
func (x *Person) GetSalary() float32 {
if x != nil {
return x.Salary
}
return 0
}
func (x *Person) GetSex() bool {
if x != nil {
return x.Sex
}
return false
}
var File_proto_base_base_proto protoreflect.FileDescriptor
var file_proto_base_base_proto_rawDesc = []byte{
0x0a, 0x15, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x62, 0x61, 0x73,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61,
0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x70, 0x62, 0x22, 0x6c, 0x0a, 0x06, 0x50, 0x65,
0x72, 0x73, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69,
0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x16,
0x0a, 0x06, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x06,
0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x65, 0x78, 0x18, 0x05, 0x20,
0x01, 0x28, 0x08, 0x52, 0x03, 0x73, 0x65, 0x78, 0x42, 0x05, 0x5a, 0x03, 0x2f, 0x70, 0x62, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_proto_base_base_proto_rawDescOnce sync.Once
file_proto_base_base_proto_rawDescData = file_proto_base_base_proto_rawDesc
)
func file_proto_base_base_proto_rawDescGZIP() []byte {
file_proto_base_base_proto_rawDescOnce.Do(func() {
file_proto_base_base_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_base_base_proto_rawDescData)
})
return file_proto_base_base_proto_rawDescData
}
var file_proto_base_base_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_proto_base_base_proto_goTypes = []interface{}{
(*Person)(nil), // 0: grpc.gateway.demo.proto.examplepb.Person
}
var file_proto_base_base_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_proto_base_base_proto_init() }
func file_proto_base_base_proto_init() {
if File_proto_base_base_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_proto_base_base_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Person); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_base_base_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proto_base_base_proto_goTypes,
DependencyIndexes: file_proto_base_base_proto_depIdxs,
MessageInfos: file_proto_base_base_proto_msgTypes,
}.Build()
File_proto_base_base_proto = out.File
file_proto_base_base_proto_rawDesc = nil
file_proto_base_base_proto_goTypes = nil
file_proto_base_base_proto_depIdxs = nil
}