Golang Gin 实战(十二)| ProtoBuf
ProtoBuf最近几年也算比较流行,它是一种语言无关,平台无关,并且可以扩展,并结构数据序列化的方法。相比JSON/XML这类文本格式的,ProtoBuf是二进制的,更快更高效。对于这么好的特性,Gin当然是支持的。
通过这篇文章你可以学到:
-
ProtoBuf数据结构
-
ProtoBuf对象如何生成Golang代码
-
Gin服务端如何序列化ProtoBuf输出
-
Go客户端如何反序列化ProtoBuf
-
Gin关于ProtoBuf的源代码分析原理实现
-
Gin Render机制分析
-
Gin如何优雅的面向接口编程
ProtoBuf数据结构
ProtoBuf的数据结构都是通过.proto
文件进行定义的,然后再通过ProtoBuf工具生成相应平台语言的类库,这样就可以被我们使用了。
1
2
3
4
5
6
7
8
9
10
11
12// 这是protobuf的版本 syntax = "proto3"; //定义包名 package module; // 定义数据结构,message 类似golang中的struct message User { string name = 1; // 定义一个string类型的字段name, 序号为1 int32 age = 2; // 定义一个int32类型的字段age, 序号为2 }
这就是一个比较简单的ProtoBuf数据结构定义了,和我们在Golang里定义Struct差不多。
生成Golang代码
有了ProtoBuf结构数据,我们就可以生成对应的Golang代码了。
首先呢,你要安装protoc
编译器,通过这个https://github.com/protocolbuffers/protobuf/releases地址下载,选择适合自己操作系统的版本。下载后要把二进制protoc
放在自己的$PATH/bin
目录中,确保可以在终端执行。
其次呢,因为ProtoBuf本身不支持GO语言,所以我们还得安装一个生成Golang代码的插件。安装方式也非常简单,通过如下代码即可:
1
2go get -u github.com/golang/protobuf/protoc-gen-go
现在我们在终端下cd到我们存放user.proto
文件的目录,执行如下代码即可生成对应的Golang代码
1
2protoc --go_out=. user.proto
--go_out=.
表示输出Golang代码文件到当前目录下,生成的文件名是user.pb.go
,规则就是filename.pb.go
。
生成的代码大家可以看一下,对于我们这么一个简单的User
结构,生成的代码量还是很大的,这里截取一些,剩下的大家自己生成后看一下。
1
2
3
4
5
6
7
8
9// 定义数据结构,message 类似golang中的struct type User struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Age int32 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` }
对应的关键核心User
对象。
在Gin中使用ProtoBuf
有了ProtoBuf对应的Golang代码,我们就可以在Gin使用了。
1
2
3
4
5
6
7
8
9
10
11
12
13func main() { r := gin.Default() r.GET("/protobuf", func(c *gin.Context) { data := &module.User{ Name: "张三", Age: 20, } c.ProtoBuf(http.StatusOK, data) }) r.Run(":8080") }
在Gin中,我们直接使用生成的module.User
即可,把它作为参数传给c.ProtoBuf
方法,这样Gin就帮我们自动序列化(其实内部实现还是golang protobuf库),然后我们就可以通过http://localhost:8080/protobuf
获取的这个序列化数据了。这个就是 Protocol Buffer API。
客户端反序列化ProtoBuf数据
反序列化也很简单,我们先启动上面的服务端 Protocol Buffer API 服务。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18func main() { resp, err := http.Get("http://localhost:8080/protobuf") if err != nil { fmt.Println(err) } else { defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) } else { user := &module.User{} proto.UnmarshalMerge(body, user) fmt.Println(*user) } } }
以上就是反序列化,得到User
对象的例子。我们运行这段代码,可以看到{张三 20 {} [] 0}
,拿到了我们想要的信息。这里的关键点,就是通过proto.UnmarshalMerge(body, user)
反序列化。
Gin ProtoBuf 源代码分析原理实现
那么Gin是如何实现ProtoBuf序列化的呢?我们从Gin的源代码分析上来看Gin比较优雅的实现以及Gin是如何面向接口编程的。
更多精彩内容请点击 https://mp.weixin.qq.com/s/zJOVBXcux0XVTGFo586Aig
最后
以上就是长情睫毛膏最近收集整理的关于Golang Gin 实战(十二)| ProtoBuf 使用和源码分析原理实现Golang Gin 实战(十二)| ProtoBuf的全部内容,更多相关Golang内容请搜索靠谱客的其他文章。
发表评论 取消回复