protobuffer在go中的使用
一、采用go mod创建go项目
mkdir protobuf-go
cd protobug-go
go mod init github.com/bobwanglong/protobuf-go
二、安装相关依赖
go get -u github.com/golang/protobuf/protoc-gen-go
touch main.go
三、创建过程
# 创建src文件
mkdir src
cd src
# 创建first文件
mkdir first
cd first
# 创建person.proto文件
touch person.proto
person.proto
syntax = "proto3";
package example.first; //不使用option指定go的包ming,编译后的go包是 “package example_first"
option go_package = "first;firstpb"; // 对编译成的go包重命名为 “package mygo"
message PersonMessage {
int32 id = 1;
bool is_adult = 2;
string name = 3;
repeated int32 lucky_nums = 4;
}
用protoc编译proto文件
# 此时的位置为 项目根目录
protoc --proto_path src/ --go_out=src/ src/first/person.proto
# 参数说明?
--proto_path //proto文件放置的路径
--go_out= //编译后输出的go文件放置的位置
src/first/person.proto //指定文件
四、调用proto文件生成的内容
在main.go中编写
package main
import (
"fmt"
firstpb "github.com/bobwanglong/protobuf-go/src/first"
)
func main() {
fmt.Println("hello world")
pm :=NewPersonMessage()
_= writeToFile("person.bin", pm)
pm2 :=&firstpb.PersonMessage{}
_=readFromFile("person.bin",pm2)
fmt.Println(pm2)
}
func NewPersonMessage() *firstpb.PersonMessage{
pm := firstpb.PersonMessage{
Id: 1234,
IsAdult: true,
Name: "bob",
LuckyNums: []int32{1, 2, 3, 4},
}
fmt.Println(pm)
pm.Name = "Nick"
fmt.Println(pm)
fmt.Printf("Id is %d\n",pm.GetId())
}
将protobuf中的信息写入文件
// 写入文件
func writeToFile(fileName string, pb proto.Message)error {
dataBytes,err :=proto.Marshal(pb)
if err !=nil{
log.Fatalln("无法序列化到bytes")
}
if err =ioutil.WriteFile(fileName,dataBytes,0644);err !=nil{
log.Fatalln("无法写入到文件",err.Error())
}
log.Println("成功写入文件")
return nil
}
//从文件中读取
func readFromFile(fileName string, pb proto.Message)error {
dataBytes,err :=ioutil.ReadFile(fileName)
if err !=nil{
log.Fatalln("read wrong",err.Error())
}
err = proto.Unmarshal(dataBytes,pb)
if err !=nil{
log.Fatalln("转化为struct的时候发生错误",err.Error())
}
return nil
}
写入jison和读取json
func toJson(pb proto.Message) string {
marshaler := jsonpb.Marshaler{Indent:" "} //Indent 缩进格式
str,err :=marshaler.MarshalToString(pb)
if err !=nil{
log.Fatalln("json序列化失败",err.Error())
}
return str
}
func fromJson(in string, pb proto.Message)error {
err :=jsonpb.UnmarshalString(in,pb)
if err !=nil{
log.Fatalln("读取json时发生错误",err.Error())
}
return nil
}
调用
// 需要引入的包
import ""github.com/golang/protobuf/jsonpb""
func main(){
//调用
pm := NewPersonMessage()
pmStr :=toJson(pm)
fmt.Println(pmStr)
pm3:=&firstpb.PersonMessage{}
_=fromJson(pmStr,pm3)
fmt.Println("pb struct:",pm3)
}
输出
# json序列化结果
{
"id": 1234,
"isAdult": true,
"name": "Nick",
"luckyNums": [
1,
2,
3,
4
]
}
# json反序列化为pb struct
pb struct: id:1234 is_adult:true name:"Nick" lucky_nums:1 lucky_nums:2 lucky_nums:3 lucky_nums:4
针对复合类型的生成
//新建一个complexpb.proto,位置在src/third文件夹
syntax = "proto3";
package example.third;
option go_package = "third;complexpb";
message DepartmentMessage{
int32 id = 1;
string name = 2;
repeated EmployeeMessage employees = 3;
DepartmentMessage parent_department = 4;
repeated DepartmentMessage children_departments = 5;
}
message EmployeeMessage{
int32 id = 1;
string name = 2;
}
main.go中编写调用
//引入
import (
complexpb "protobuf-go/src/third"
)
// 复合类型
func NewDepartmentMessage() *complexpb.DepartmentMessage {
dm := &complexpb.DepartmentMessage{
Id: 1234,
Name: "开发部",
Employees: []*complexpb.EmployeeMessage{
&complexpb.EmployeeMessage{
Id: 12,
Name: "Dave",
},
&complexpb.EmployeeMessage{
Id: 34,
Name: "Mike",},
},
ParentDepartment: &complexpb.DepartmentMessage{
Id: 1211,
Name: "总公司",},
ChildrenDepartments: nil,
}
return dm
}
func main(){
dm :=NewDepartmentMessage()
fmt.Println(dm)
}
// 输出结果
id:1234 name:"开发部" employees:{id:12 name:"Dave"} employees:{id:34 name:"Mike"} parent_department:{id:1211 name:"总公司"}