内容简介:和安装成功后,会在该
简介
和 http 中常用的 json 协议一样, protobuf 也是用来传输数据的,但是它使用二进制格式,传输效率更高。
安装
- 下载
protoc二进制程序
下载链接
在windows上,选择protoc-3.7.0-rc-2-win64.zip 进行下载。
压缩包中有两个文件夹:
将压缩包中文件夹.png
bin目录下的protoc.exe拷贝到GOPATH/bin目录下,将include/目录下的google文件夹拷贝GOPATH/src目录下(只有使用protobuf的一些内置结构才需要用到该文件夹内的文件,这次并不会用到这个文件夹)。 - 安装
protobuf的编译器插件protoc-gen-go
protoc程序会调用protoc-gen-go,将.proto文件生成golang代码。可以使用go get命令安装:
go get -u -v github.com/golang/protobuf/protoc-gen-go
安装成功后,会在 GOPATH/bin 下生成 protoc-gen-go.exe 程序。
例子
该 demo 为官网 tutorial 的简化版本。
在GOPATH/src/all-demo下,目录结构为:
protobuf-demo
demo1
addressbook
addressbook.pb.go
addressbook.proto
main.go
编写、编译addressbook.proto文件
其中 addressbook.proto 文件为:
// [START declaration]
syntax = "proto3";
package addressbook;
// [END declaration]
// [START messages]
message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person people = 1;
}
// [END messages]
其中:
-
syntax设置语法类型,有proto2和proto3两种语法。 -
package addressbook可以设置生成的golang代码的包名。 -
message对应于golang中的struct,可以看到文件中一共定义了Person,PhoneNumber,AddressBook3个message,其中PhoneNumber是Person的嵌套类型。 -
message中有字段,可以是int,string,枚举或者其他消息类型。 -
repeated表示该字段可以不止一个,类似于golang中的slice。
编译
命令行进入 GOPATH/src/all-demo/protobuf-demo/demo1/addressbook ,
执行 protoc --go_out=. addressbook.proto ,会在该目录下生成 addressbook.pb.go 文件。
其中 --go_out 指定生成的 golang 文件的目录。
addressbook.pb.go 部分源码如下:
// 可以看到包名为addressbook
package addressbook
// [START messages]
type Person struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Id int32 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"`
Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
Phones []*Person_PhoneNumber `protobuf:"bytes,4,rep,name=phones,proto3" json:"phones,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type Person_PhoneNumber struct {
Number string `protobuf:"bytes,1,opt,name=number,proto3" json:"number,omitempty"`
Type Person_PhoneType `protobuf:"varint,2,opt,name=type,proto3,enum=addressbook.Person_PhoneType" json:"type,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
// Our address book file is just one of these.
type AddressBook struct {
People []*Person `protobuf:"bytes,1,rep,name=people,proto3" json:"people,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
编写main.go
代码主要测试 proto.Marshal 和 proto.UnMarshal 的功能。先定义一个 pb.AddressBook 结构体,并将其初始化,用 proto.Marshal 将其序列化成二进制数据,写入文件,再将其从文件中读取,使用 proto.UnMarshal 反序列化成结构体。
代码如下:
package main
import (
"fmt"
pb "all-demo/protobuf-demo/demo1/addressbook"
"io/ioutil"
"log"
"github.com/golang/protobuf/proto"
)
func main() {
// 自定义AddressBook内容
book := &pb.AddressBook{
People: []*pb.Person {
&pb.Person{
Id: 1,
Name: "zyq",
Email: "77@qq.com",
Phones: []*pb.Person_PhoneNumber{
&pb.Person_PhoneNumber {
Number: "11111",
Type: pb.Person_MOBILE,
},
&pb.Person_PhoneNumber {
Number: "22222",
Type: pb.Person_HOME,
},
},
},
},
}
fmt.Println("book : ",book)
fname := "address.dat"
// 将book进行序列化
out, err := proto.Marshal(book)
if err != nil {
log.Fatalln("Failed to encode address book:", err)
}
// 将序列化的内容写入文件
if err := ioutil.WriteFile(fname, out, 0644); err != nil {
log.Fatalln("Failed to write address book:", err)
}
// 读取写入的二进制数据
in, err := ioutil.ReadFile(fname)
if err != nil {
log.Fatalln("Error reading file:", err)
}
// 定义一个空的结构体
book2 := &pb.AddressBook{}
// 将从文件中读取的二进制进行反序列化
if err := proto.Unmarshal(in, book2); err != nil {
log.Fatalln("Failed to parse address book:", err)
}
fmt.Println("book2: ",book2)
}
执行结果为:
book : people:<name:"zyq" id:1 email:"77@qq.com" phones:<number:"11111" > phones:<number:"22222" type:HOME > > book2: people:<name:"zyq" id:1 email:"77@qq.com" phones:<number:"11111" > phones:<number:"22222" type:HOME > >
问题:
- 还有很多语法不了解。
-
proto.UnMarshal函数的声明为func Unmarshal(buf []byte, pb Message) error,该函数的第二个参数为proto.Message接口,在网络传输中,服务端怎么知道客户端发过来的到底是哪一种message。
参考
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- RecyclerView使用指南(一)—— 基本使用
- 如何使用Meteorjs使用URL参数
- 使用 defer 还是不使用 defer?
- 使用 Typescript 加强 Vuex 使用体验
- [译] 何时使用 Rust?何时使用 Go?
- UDP协议的正确使用场合(谨慎使用)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
UNIX网络编程
史蒂文斯、芬纳、鲁道夫 / 杨继张 / 清华大学出版社 / 2006-1 / 98.00元
《UNIX网络编程》(第1卷)(套接口API第3版)第1版和第2版由已故UNIX网络专家W. Richard Stevens博士独自编写。《UNIX网络编程》(第1卷)(套接口API第3版)是3版,由世界著名网络专家Bill Fenner和Andrew M. Rudoff执笔,根据近几年网络技术的发展,对上一版进行全面修订,增添了IPv6的更新过的信息、SCTP协议和密钥管理套接口的内容,删除了X......一起来看看 《UNIX网络编程》 这本书的介绍吧!