1. 安装
在网上看了很多教程,都提到要安装 protoc 与 protoc-gen-go,但通过尝试之后并不能正确安装 protoc,顺便记录一下能够顺利安装 protoc 与 protoc-gen-go 的方法。前提是已经默认安装好了 go。
-
安装 protoc
- 在该链接下下载protoc-3.3.0-win32.zip的包
- 将文件解压到某一文件夹
- 将解压出来的文件夹下的 /bin/protoc.exe 二进制的路径添加到环境变量中
-
安装 protoc-gen-go
- 在终端直接执行
go get -u github.com/golang/protobuf/protoc-gen-go
,可以在你的%GOPATH%/bin
路径下找到一个 protoc-gen-go.exe(这一步不能完成的话,考虑开个全局的翻墙)
- 在终端直接执行
至此已经完成了 protoc 与 protoc-gen-go
2. 使用
在 windows 的 cmd 尝试通过命令行生成*.pb.go 文件失败,是在 Git bash 中生成成功的。
新建一个 test.proto 文件
package tutorial;
message Person {
required string name = 1;
required int32 age = 2;
optional string email = 3;
}
进入test.proto 文件所在文件夹,在 Git bash 中执行
protoc --plugin=protoc-gen-go=/f/gopath/bin/protoc-gen-go.exe --go_out=./ test.proto
其中 --go_out 后面是输出文件的路径与输入 proto 文件的路径,但是执行之后会出现如下错误
根据报错,我们知道,需要在 .proto 文件的第一行增加一行版本说明,如下
syntax = "proto2";
package tutorial;
message Person {
required string name = 1;
required int32 age = 2;
optional string email = 3;
}
}
再次运行上面的命令行,便可在你指定的目录下得到test.pb.go
文件,文件内容如下:
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: test.proto
/*
Package tutorial is a generated protocol buffer package.
It is generated from these files:
test.proto
It has these top-level messages:
Person
*/
package tutorial
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Person struct {
Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
Age *int32 `protobuf:"varint,2,req,name=age" json:"age,omitempty"`
Email *string `protobuf:"bytes,3,opt,name=email" json:"email,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *Person) Reset() { *m = Person{} }
func (m *Person) String() string { return proto.CompactTextString(m) }
func (*Person) ProtoMessage() {}
func (*Person) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *Person) GetName() string {
if m != nil && m.Name != nil {
return *m.Name
}
return ""
}
func (m *Person) GetAge() int32 {
if m != nil && m.Age != nil {
return *m.Age
}
return 0
}
func (m *Person) GetEmail() string {
if m != nil && m.Email != nil {
return *m.Email
}
return ""
}
func init() {
proto.RegisterType((*Person)(nil), "tutorial.Person")
}
func init() { proto.RegisterFile("test.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 106 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e,
0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x28, 0x29, 0x2d, 0xc9, 0x2f, 0xca, 0x4c, 0xcc,
0x51, 0x72, 0xe1, 0x62, 0x0b, 0x48, 0x2d, 0x2a, 0xce, 0xcf, 0x13, 0x12, 0xe2, 0x62, 0xc9, 0x4b,
0xcc, 0x4d, 0x95, 0x60, 0x54, 0x60, 0xd2, 0xe0, 0x0c, 0x02, 0xb3, 0x85, 0x04, 0xb8, 0x98, 0x13,
0xd3, 0x53, 0x25, 0x98, 0x14, 0x98, 0x34, 0x58, 0x83, 0x40, 0x4c, 0x21, 0x11, 0x2e, 0xd6, 0xd4,
0xdc, 0xc4, 0xcc, 0x1c, 0x09, 0x66, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x08, 0x07, 0x10, 0x00, 0x00,
0xff, 0xff, 0x16, 0x57, 0xf0, 0x40, 0x5c, 0x00, 0x00, 0x00,
}
可以看到,protoc 根据我们的 test.proto 文件,生成的test.pb.go 中,定义了相关结构体,相关结构体中相关字段的读取方法,以及其他一些方法。
3. 问题
我在 cmd 终端下执行上述命令时,总是报错说Missing input file
,但不知道为什么。而且我在 git bash 中,如果不进入到 test.proto 文件的目录下的话,也是报 Missing input file
的错。这两个问题还没解决。