找回密码
 立即注册
查看: 229|回复: 0

Golang Gin 实战(十二)| ProtoBuf 使用和源码分析原理 ...

[复制链接]
发表于 2022-2-14 11:50 | 显示全部楼层 |阅读模式
ProtoBuf最近几年也算比较流行,它是一种语言无关,平台无关,并且可以扩展,并结构数据序列化的方法。相比JSON/XML这类文本格式的,ProtoBuf是二进制的,更快更高效。对于这么好的特性,Gin当然是支持的。
通过这篇文章你可以学到:

  • ProtoBuf数据结构
  • ProtoBuf对象如何生成Golang代码
  • Gin服务端如何序列化ProtoBuf输出
  • Go客户端如何反序列化ProtoBuf
  • Gin关于ProtoBuf的源代码分析原理实现
  • Gin Render机制分析
  • Gin如何优雅的面向接口编程
ProtoBuf数据结构

ProtoBuf的数据结构都是通过.proto文件进行定义的,然后再通过ProtoBuf工具生成相应平台语言的类库,这样就可以被我们使用了。
// 这是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代码的插件。安装方式也非常简单,通过如下代码即可:
go get -u github.com/golang/protobuf/protoc-gen-go现在我们在终端下cd到我们存放user.proto文件的目录,执行如下代码即可生成对应的Golang代码
protoc --go_out=. user.proto--go_out=.表示输出Golang代码文件到当前目录下,生成的文件名是user.pb.go,规则就是filename.pb.go。
生成的代码大家可以看一下,对于我们这么一个简单的User结构,生成的代码量还是很大的,这里截取一些,剩下的大家自己生成后看一下。
// 定义数据结构,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使用了。
func 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 服务。
func 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的面向接口的编程。剩下的精彩内容请点击:
精彩文章推荐

Golang Gin 实战(十一)| HTML模板渲染
Golang Gin 实战(十)| XML渲染
Golang Gin 实战(九)| JSONP跨域和劫持
Golang Gin 实战(八)| JSON渲染输出
Golang Gin 实战(七)| 分组路由源代码分析
Golang Gin 实战(六)| 获取Form表单参数和原理分析
Golang Gin 实战(五)| 接收数组和map
Golang Gin 实战(四)| URL查询参数的获取和原理分析
Golang Gin 实战(三)| 路由参数
Golang Gin 实战(二)| 简便的Restful API 实现
Golang Gin 实战(一)| 快速安装入门
我有几个的Go语言交流微信群,可以扫码关注公众号flysnow_org或者网站 https://www.flysnow.org/,加我好友,我拉你进来。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-18 02:22 , Processed in 0.089786 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表