在 Go 语言中使用 Protobuf

简介

Protobuf 源码中默认实现了对 C++, Java, C#, Python 等语言的生成器插件,但是没有 Go 语言的生成器插件。Go 语言的生成器插件是在另一个叫 golang/protobuf 的项目中提供的,也叫 goprotobuf,这篇文章主要就是介绍如何在 Go 语言中使用 Protobuf。

安装 golang/protobuf

go get -u github.com/golang/protobuf/protoc-gen-go

执行上述命令之后,protoc-gen-go 二进制程序默认会安装在 $GOBIN 目录中。

注:
golang/protobuf 中包含了 github.com/golang/protobuf/proto 库,这个库定义了 .proto 文件中声明的类型和方法所对应的 Go 语言表示的类型和方法,也就是由 protoc-gen-go 所生成的 Go 源码文件中所有需要引用到的类型和方法。

比如 proto/lib.go 中包含大量常用的类型及方法:

proto.String()
proto.Int64()
proto.Uint64()
proto.Bool()
proto.Marshal()
proto.Unmarshal()
proto.Message

编译 .proto 文件

执行 protoc,并使用 --go_out 选项指定输出目录,即可生成 Go 源码文件。因为安装了 protoc-gen-go 之后,--go_out 选项会自动搜索 protoc-gen-go,只要其在 PATH 目录中可以找到即可。

--go_out 支持以下参数

  • plugins=plugin1+plugin2 指定插件,目前只支持 grpc,即:plugins=grpc
  • M 参数 指定导入的.proto文件路径编译后对应的golang包名(不指定本参数默认就是.proto文件中import语句的路径)
  • import_prefix=xxx 为所有 import 路径添加前缀,主要用于编译子目录内的多个 proto 文件,这个参数按理说很有用,尤其适用替代一些情况时的 M 参数。
  • import_path=foo/bar 用于指定未声明 package 或 go_package 的文件的包名,最右面的斜线前的字符会被忽略

例子

(1)编写一个 msg.proto IDL 文件,如下:

syntax="proto3";
package example;

message Msg {
    int32 msgType  = 1;
    string MsgInfo = 2;
    string MsgFrom = 3;
}
注意:
  • 在最新版的 Protobuf 中,强制要求 proto 文件必须指定版本,否则编译报错
  • 这里定义的所有字段(无论大小写),在生成的 Go 语言中的结构体中都是导出字段,也就是都会变成大写。

(2)编译 .proto 文件,生成 Go 语言文件

执行 protoc --go_out=. msg.proto 生成对应的 msg.pb.go 文件
进入 msg.pb.go 所在目录,执行 go install 生成相应的包。

(3)在 Go 程序中使用 protobuf

创建 main.go,并输入如下内容:

package main

import (
    "github.com/google/protobuf/proto"
    "example"
    "fmt"
    "os"
)

func main() {
    msg_test := &example.Msg{
        MsgType: proto.Int32(1),
        MsgInfo: proto.String("I am hahaya."),
        MsgFrom: proto.String("127.0.0.1"),
    }
    
    in_data, err := proto.Marshal(msg_test)
    if err != nil {
        fmt.Println("Marshaling error: ", err)
        os.Exit(1)
    }
    
    msg_encoding := &example.Msg{}
    err = proto.Unmarshal(in_data, msg_encoding)
    if err != nil {
        fmt.Println("Unmarshaling error: ", err)
        os.Exit(1)
    }
    fmt.Printf("msg type: %d\n", msg_encoding.GetMsgType())
    fmt.Printf("msg info: %s\n", msg_encoding.MsgInfo)
    fmt.Printf("msg from: %s\n", msg_encoding.MsgFrom)
}

知识扩展

除了 Google 官方提供的这款 golang/protobuf 插件,还有一款非常优秀的开源第三方库 gogo/protobuf,其作为官方的 fork,做了非常多的性能上的优化,能提供更加快速的编解码实现。

gogo/protobuf 的源码地址:https://github.com/gogo/protobuf

根据其官方介绍,它提供了许多不同优化级别的实现,比如:

proto-gen-gofast
proto-gen-gogo
proto-gen-gogofast
proto-gen-gogofaster
proto-gen-gogoslick
...
gogo/protobuf 的安装和使用

安装

go get -u github.com/gogo/protobuf/protoc-gen-gofast

使用

protoc --gofast_out=. test.proto

全文完

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容