目錄
它的優勢及特點這裏不贅述了,網上一大堆相關說明。
數據類型的對應表
.proto Type | C++ Type | Java Type | Go Type | PHP Type |
---|---|---|---|---|
double | double | double | float64 | float |
float | float | float | float32 | float |
int32 | int32 | int | int32 | integer |
int64 | int64 | long | int64 | integer/string |
uint32 | uint32 | int | uint32 | integer |
uint64 | uint64 | long | uint64 | integer/string |
sint32 | int32 | int | int32 | integer |
sint64 | int64 | long | int64 | integer/string |
fixed32 | uint32 | int | uint32 | integer |
fixed64 | uint64 | long | uint64 | integer/string |
sfixed32 | int32 | int | int32 | integer |
sfixed64 | int64 | long | int64 | integer/string |
bool | bool | boolean | bool | boolean |
string | string | String | string | string |
bytes | string | ByteString | []byte | string |
實踐的一個例子
新建一個項目,新建一個目錄存放.proto文件,這裏以學生實體爲例,儘可能多的使用了多個類型,目錄下新建student.proto文件如下:
// 如不涉及rpc,可直接protoc --go_out=. *.proto
// 指定版本,此處採用proto3語法
syntax = "proto3";
//包名,通過protoc生成時的go文件對應的package
package student;
// 性別,枚舉。枚舉類型第一個字段必須爲0
enum Gender {
Male = 0; // 男
Female = 1; // 女
}
// 學生信息
message Student {
int32 id = 1; // 學號
string name = 2; // 姓名
Gender gender = 3; // 性別
map<string, Course> Score = 4; // 該學生選修的課程及其對應的課程具體信息
}
message Course{
float duration = 1; // 課程週期,單位默認小時
float score = 2; // 所修學分
bool isPass = 3; // 考覈結果是否通過
}
cd進入該.proto文件所在的目錄下,終端執行命令protoc --go_out=. student.proto 或
protoc --go_out=. *.proto
多個的話用後者即可。該目錄下會生成對應的student.pb.go
(生成方式及環境搭建可移步https://blog.csdn.net/HYZX_9987/article/details/106462026)
看看生成的go文件:
// 如不涉及rpc,可直接protoc --go_out=. *.proto
// 指定版本,此處採用proto3語法
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.24.0
// protoc v3.12.1
// source: student.proto
//包名,通過protoc生成時的go文件對應的package
package student
import (
proto "github.com/golang/protobuf/proto"
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)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
// 性別,枚舉。枚舉類型第一個字段必須爲0
type Gender int32
const (
Gender_Male Gender = 0 // 男
Gender_Female Gender = 1 // 女
)
// Enum value maps for Gender.
var (
Gender_name = map[int32]string{
0: "Male",
1: "Female",
}
Gender_value = map[string]int32{
"Male": 0,
"Female": 1,
}
)
func (x Gender) Enum() *Gender {
p := new(Gender)
*p = x
return p
}
func (x Gender) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Gender) Descriptor() protoreflect.EnumDescriptor {
return file_student_proto_enumTypes[0].Descriptor()
}
func (Gender) Type() protoreflect.EnumType {
return &file_student_proto_enumTypes[0]
}
func (x Gender) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Gender.Descriptor instead.
func (Gender) EnumDescriptor() ([]byte, []int) {
return file_student_proto_rawDescGZIP(), []int{0}
}
// 學生信息
type Student 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"` // 姓名
Gender Gender `protobuf:"varint,3,opt,name=gender,proto3,enum=student.Gender" json:"gender,omitempty"` // 性別
Score map[string]*Course `protobuf:"bytes,4,rep,name=Score,proto3" json:"Score,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // 該學生選修的課程及其對應的課程具體信息
}
func (x *Student) Reset() {
*x = Student{}
if protoimpl.UnsafeEnabled {
mi := &file_student_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Student) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Student) ProtoMessage() {}
func (x *Student) ProtoReflect() protoreflect.Message {
mi := &file_student_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 Student.ProtoReflect.Descriptor instead.
func (*Student) Descriptor() ([]byte, []int) {
return file_student_proto_rawDescGZIP(), []int{0}
}
func (x *Student) GetId() int32 {
if x != nil {
return x.Id
}
return 0
}
func (x *Student) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Student) GetGender() Gender {
if x != nil {
return x.Gender
}
return Gender_Male
}
func (x *Student) GetScore() map[string]*Course {
if x != nil {
return x.Score
}
return nil
}
type Course struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Duration float32 `protobuf:"fixed32,1,opt,name=duration,proto3" json:"duration,omitempty"` // 課程週期,單位默認小時
Score float32 `protobuf:"fixed32,2,opt,name=score,proto3" json:"score,omitempty"` // 所修學分
IsPass bool `protobuf:"varint,3,opt,name=isPass,proto3" json:"isPass,omitempty"` // 考覈結果是否通過
}
func (x *Course) Reset() {
*x = Course{}
if protoimpl.UnsafeEnabled {
mi := &file_student_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Course) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Course) ProtoMessage() {}
func (x *Course) ProtoReflect() protoreflect.Message {
mi := &file_student_proto_msgTypes[1]
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 Course.ProtoReflect.Descriptor instead.
func (*Course) Descriptor() ([]byte, []int) {
return file_student_proto_rawDescGZIP(), []int{1}
}
func (x *Course) GetDuration() float32 {
if x != nil {
return x.Duration
}
return 0
}
func (x *Course) GetScore() float32 {
if x != nil {
return x.Score
}
return 0
}
func (x *Course) GetIsPass() bool {
if x != nil {
return x.IsPass
}
return false
}
var File_student_proto protoreflect.FileDescriptor
var file_student_proto_rawDesc = []byte{
0x0a, 0x0d, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x07, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x22, 0xd4, 0x01, 0x0a, 0x07, 0x53, 0x74, 0x75,
0x64, 0x65, 0x6e, 0x74, 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, 0x27, 0x0a, 0x06, 0x67, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x75, 0x64, 0x65,
0x6e, 0x74, 0x2e, 0x47, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x12, 0x31, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x1b, 0x2e, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x74, 0x75, 0x64, 0x65,
0x6e, 0x74, 0x2e, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x53,
0x63, 0x6f, 0x72, 0x65, 0x1a, 0x49, 0x0a, 0x0a, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x45, 0x6e, 0x74,
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x03, 0x6b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f,
0x75, 0x72, 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
0x52, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x64, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69,
0x73, 0x50, 0x61, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x50,
0x61, 0x73, 0x73, 0x2a, 0x1e, 0x0a, 0x06, 0x47, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x08, 0x0a,
0x04, 0x4d, 0x61, 0x6c, 0x65, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x65, 0x6d, 0x61, 0x6c,
0x65, 0x10, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_student_proto_rawDescOnce sync.Once
file_student_proto_rawDescData = file_student_proto_rawDesc
)
func file_student_proto_rawDescGZIP() []byte {
file_student_proto_rawDescOnce.Do(func() {
file_student_proto_rawDescData = protoimpl.X.CompressGZIP(file_student_proto_rawDescData)
})
return file_student_proto_rawDescData
}
var file_student_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_student_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_student_proto_goTypes = []interface{}{
(Gender)(0), // 0: student.Gender
(*Student)(nil), // 1: student.Student
(*Course)(nil), // 2: student.Course
nil, // 3: student.Student.ScoreEntry
}
var file_student_proto_depIdxs = []int32{
0, // 0: student.Student.gender:type_name -> student.Gender
3, // 1: student.Student.Score:type_name -> student.Student.ScoreEntry
2, // 2: student.Student.ScoreEntry.value:type_name -> student.Course
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_student_proto_init() }
func file_student_proto_init() {
if File_student_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_student_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Student); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_student_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Course); 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_student_proto_rawDesc,
NumEnums: 1,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_student_proto_goTypes,
DependencyIndexes: file_student_proto_depIdxs,
EnumInfos: file_student_proto_enumTypes,
MessageInfos: file_student_proto_msgTypes,
}.Build()
File_student_proto = out.File
file_student_proto_rawDesc = nil
file_student_proto_goTypes = nil
file_student_proto_depIdxs = nil
}
新建main.go隨便搞點數據,分別以json和protobuf進行byte和結構化之間的轉換,如下:
package main
import (
"encoding/json"
"fmt"
"github.com/golang/protobuf/proto"
student "protobuf-basic/protobuf"
)
func makeStudent(id int32, name, courseName string, gender student.Gender, duration, score float32) *student.Student {
stu := &student.Student{
Id: id,
Name: name,
Gender: gender,
Score: map[string]*student.Course{
"哲學": &student.Course{
Duration: 16.0,
Score: 2.5,
IsPass: true,
},
courseName: &student.Course{
Duration: duration,
Score: score,
IsPass: true,
},
},
}
return stu
}
func main() {
stu0 := makeStudent(1416271200, "王五", "中外音樂鑑賞", student.Gender_Male, 14.5, 2.0)
b0, _ := json.Marshal(stu0) // 編碼
fmt.Println("[json-byte]學生:", b0)
s0 := &student.Student{}
json.Unmarshal(b0, s0) // 解碼
fmt.Println("[struct]學生:", s0)
fmt.Println("------------------------")
stu1 := makeStudent(1416271201, "王六", "中外音樂鑑賞", student.Gender_Male, 14.5, 2.0)
b1, _ := proto.Marshal(stu1) // 編碼
fmt.Println("[protobuf-byte]學生:", b1)
s1 := &student.Student{}
proto.Unmarshal(b1, s1) // 解碼
fmt.Print("[struct]學生:", s1)
}
控制檯:
[json-byte]學生: [123 34 105 100 34 58 49 52 49 54 50 55 49 50 48 48 44 34 110 9
7 109 101 34 58 34 231 142 139 228 186 148 34 44 34 83 99 111 114 101 34 58 123
34 228 184 173 229 164 150 233 159 179 228 185 144 233 137 180 232 181 143 34 58
123 34 100 117 114 97 116 105 111 110 34 58 49 52 46 53 44 34 115 99 111 114 10
1 34 58 50 44 34 105 115 80 97 115 115 34 58 116 114 117 101 125 44 34 229 147 1
78 229 173 166 34 58 123 34 100 117 114 97 116 105 111 110 34 58 49 54 44 34 115
99 111 114 101 34 58 50 46 53 44 34 105 115 80 97 115 115 34 58 116 114 117 101
125 125 125]
[struct]學生: id:1416271200 name:"王五" Score:{key:"中外音樂鑑賞" value:{dura
tion:14.5 score:2 isPass:true}} Score:{key:"哲學" value:{duration:16 score:
2.5 isPass:true}}
------------------------
[protobuf-byte]學生: [8 225 170 170 163 5 18 6 231 142 139 229 133 173 34 22 10
6 229 147 178 229 173 166 18 12 13 0 0 128 65 21 0 0 32 64 24 1 34 34 10 18 228
184 173 229 164 150 233 159 179 228 185 144 233 137 180 232 181 143 18 12 13 0 0
104 65 21 0 0 0 64 24 1]
[struct]學生:id:1416271201 name:"王六" Score:{key:"中外音樂鑑賞" value:{durat
ion:14.5 score:2 isPass:true}} Score:{key:"哲學" value:{duration:16 score:2
.5 isPass:true}}