Go 结构的 Protobuf 编译器没有为导入生成正确的包名称?
Protobuf compiler for Go structs not generating the right package name for imports?
考虑以下带有 Go 模块 github.com/kurtpeek/proto-example
和以下目录结构的示例项目(.proto
文件位于 proto
目录中,生成的 Go 代码位于 gen/go
中) :
.
├── gen
│ └── go
│ ├── author
│ │ └── author.pb.go
│ └── book
│ └── book.pb.go
├── go.mod
├── go.sum
├── main.go
└── proto
├── author
│ └── author.proto
└── book
└── book.proto
这里author.proto
读
syntax="proto3";
package author;
message Author {
string name = 1;
}
和 book.proto
像这样导入 author.proto
:
syntax="proto3";
package book;
import "author/author.proto";
message Book {
string title = 1;
author.Author author = 2;
}
我通过 proto/
目录中的 运行
生成了 .pb.go
文件
protoc book/book.proto --go_out=../gen/go
和
protoc author/author.proto --go_out=../gen/go
问题是 author
在 book.pb.go
中导入的包名称只是 "author"
:
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: book/book.proto
package book
import (
author "author"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
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.ProtoPackageIsVersion3 // please upgrade the proto package
type Book struct {
Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"`
Author *author.Author `protobuf:"bytes,2,opt,name=author,proto3" json:"author,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Book) Reset() { *m = Book{} }
func (m *Book) String() string { return proto.CompactTextString(m) }
func (*Book) ProtoMessage() {}
func (*Book) Descriptor() ([]byte, []int) {
return fileDescriptor_ee9082fb44230b1b, []int{0}
}
func (m *Book) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Book.Unmarshal(m, b)
}
func (m *Book) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Book.Marshal(b, m, deterministic)
}
func (m *Book) XXX_Merge(src proto.Message) {
xxx_messageInfo_Book.Merge(m, src)
}
func (m *Book) XXX_Size() int {
return xxx_messageInfo_Book.Size(m)
}
func (m *Book) XXX_DiscardUnknown() {
xxx_messageInfo_Book.DiscardUnknown(m)
}
var xxx_messageInfo_Book proto.InternalMessageInfo
func (m *Book) GetTitle() string {
if m != nil {
return m.Title
}
return ""
}
func (m *Book) GetAuthor() *author.Author {
if m != nil {
return m.Author
}
return nil
}
func init() {
proto.RegisterType((*Book)(nil), "book.Book")
}
func init() { proto.RegisterFile("book/book.proto", fileDescriptor_ee9082fb44230b1b) }
var fileDescriptor_ee9082fb44230b1b = []byte{
// 108 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4f, 0xca, 0xcf, 0xcf,
0xd6, 0x07, 0x11, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x2c, 0x20, 0xb6, 0x94, 0x70, 0x62,
0x69, 0x49, 0x46, 0x7e, 0x91, 0x3e, 0x84, 0x82, 0x48, 0x29, 0xb9, 0x70, 0xb1, 0x38, 0xe5, 0xe7,
0x67, 0x0b, 0x89, 0x70, 0xb1, 0x96, 0x64, 0x96, 0xe4, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70,
0x06, 0x41, 0x38, 0x42, 0x6a, 0x5c, 0x6c, 0x10, 0xd5, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46,
0x7c, 0x7a, 0x50, 0xcd, 0x8e, 0x60, 0x2a, 0x08, 0x2a, 0x9b, 0xc4, 0x06, 0x36, 0xcc, 0x18, 0x10,
0x00, 0x00, 0xff, 0xff, 0x2c, 0x89, 0x1f, 0x45, 0x7a, 0x00, 0x00, 0x00,
}
我希望生成的 go 代码能够使用正确的包名称相互导入,这样 book.pb.go
就会像这样开始:
package book
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
author "github.com/kurtpeek/proto-example/gen/go/author"
)
如何使生成代码所在的 Go 模块的 Protobuf 编译器 'aware'?
(我怀疑我需要指定 option go_package
(参见 https://developers.google.com/protocol-buffers/docs/gotutorial),但这样做似乎并没有改变生成的代码。
你就快完成了!我怀疑你可能被相对路径咬了...
如果你的原型文件是这样开始的:
package author;
option go_package = "github.com/kurtpeek/proto-example/gen/go/author";
和
package book;
import "author/author.proto";
option go_package = "github.com/kurtpeek/proto-example/gen/go/book";
并使用构建命令(使用相对路径)
mkdir -p gen/go
protoc book/book.proto --go_out=gen/go
protoc author/author.proto --go_out=gen/go
您生成的代码将出现在这些相对 路径(到您的 CWD):
gen/go/github.com/kurtpeek/proto-example/gen/go/author/author.pb.go
gen/go/github.com/kurtpeek/proto-example/gen/go/book/book.pb.go
生成的 book
包应该有所需的导入:
package book
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
author "github.com/kurtpeek/proto-example/gen/go/author"
math "math"
)
如果要将生成的代码放在特定目录中,请使用绝对路径:
mkdir -p /some/absolute/path
protoc my.proto --go_out=/some/absolute/path
考虑以下带有 Go 模块 github.com/kurtpeek/proto-example
和以下目录结构的示例项目(.proto
文件位于 proto
目录中,生成的 Go 代码位于 gen/go
中) :
.
├── gen
│ └── go
│ ├── author
│ │ └── author.pb.go
│ └── book
│ └── book.pb.go
├── go.mod
├── go.sum
├── main.go
└── proto
├── author
│ └── author.proto
└── book
└── book.proto
这里author.proto
读
syntax="proto3";
package author;
message Author {
string name = 1;
}
和 book.proto
像这样导入 author.proto
:
syntax="proto3";
package book;
import "author/author.proto";
message Book {
string title = 1;
author.Author author = 2;
}
我通过 proto/
目录中的 运行
.pb.go
文件
protoc book/book.proto --go_out=../gen/go
和
protoc author/author.proto --go_out=../gen/go
问题是 author
在 book.pb.go
中导入的包名称只是 "author"
:
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: book/book.proto
package book
import (
author "author"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
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.ProtoPackageIsVersion3 // please upgrade the proto package
type Book struct {
Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"`
Author *author.Author `protobuf:"bytes,2,opt,name=author,proto3" json:"author,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Book) Reset() { *m = Book{} }
func (m *Book) String() string { return proto.CompactTextString(m) }
func (*Book) ProtoMessage() {}
func (*Book) Descriptor() ([]byte, []int) {
return fileDescriptor_ee9082fb44230b1b, []int{0}
}
func (m *Book) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Book.Unmarshal(m, b)
}
func (m *Book) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Book.Marshal(b, m, deterministic)
}
func (m *Book) XXX_Merge(src proto.Message) {
xxx_messageInfo_Book.Merge(m, src)
}
func (m *Book) XXX_Size() int {
return xxx_messageInfo_Book.Size(m)
}
func (m *Book) XXX_DiscardUnknown() {
xxx_messageInfo_Book.DiscardUnknown(m)
}
var xxx_messageInfo_Book proto.InternalMessageInfo
func (m *Book) GetTitle() string {
if m != nil {
return m.Title
}
return ""
}
func (m *Book) GetAuthor() *author.Author {
if m != nil {
return m.Author
}
return nil
}
func init() {
proto.RegisterType((*Book)(nil), "book.Book")
}
func init() { proto.RegisterFile("book/book.proto", fileDescriptor_ee9082fb44230b1b) }
var fileDescriptor_ee9082fb44230b1b = []byte{
// 108 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4f, 0xca, 0xcf, 0xcf,
0xd6, 0x07, 0x11, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x2c, 0x20, 0xb6, 0x94, 0x70, 0x62,
0x69, 0x49, 0x46, 0x7e, 0x91, 0x3e, 0x84, 0x82, 0x48, 0x29, 0xb9, 0x70, 0xb1, 0x38, 0xe5, 0xe7,
0x67, 0x0b, 0x89, 0x70, 0xb1, 0x96, 0x64, 0x96, 0xe4, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70,
0x06, 0x41, 0x38, 0x42, 0x6a, 0x5c, 0x6c, 0x10, 0xd5, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46,
0x7c, 0x7a, 0x50, 0xcd, 0x8e, 0x60, 0x2a, 0x08, 0x2a, 0x9b, 0xc4, 0x06, 0x36, 0xcc, 0x18, 0x10,
0x00, 0x00, 0xff, 0xff, 0x2c, 0x89, 0x1f, 0x45, 0x7a, 0x00, 0x00, 0x00,
}
我希望生成的 go 代码能够使用正确的包名称相互导入,这样 book.pb.go
就会像这样开始:
package book
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
author "github.com/kurtpeek/proto-example/gen/go/author"
)
如何使生成代码所在的 Go 模块的 Protobuf 编译器 'aware'?
(我怀疑我需要指定 option go_package
(参见 https://developers.google.com/protocol-buffers/docs/gotutorial),但这样做似乎并没有改变生成的代码。
你就快完成了!我怀疑你可能被相对路径咬了...
如果你的原型文件是这样开始的:
package author;
option go_package = "github.com/kurtpeek/proto-example/gen/go/author";
和
package book;
import "author/author.proto";
option go_package = "github.com/kurtpeek/proto-example/gen/go/book";
并使用构建命令(使用相对路径)
mkdir -p gen/go
protoc book/book.proto --go_out=gen/go
protoc author/author.proto --go_out=gen/go
您生成的代码将出现在这些相对 路径(到您的 CWD):
gen/go/github.com/kurtpeek/proto-example/gen/go/author/author.pb.go
gen/go/github.com/kurtpeek/proto-example/gen/go/book/book.pb.go
生成的 book
包应该有所需的导入:
package book
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
author "github.com/kurtpeek/proto-example/gen/go/author"
math "math"
)
如果要将生成的代码放在特定目录中,请使用绝对路径:
mkdir -p /some/absolute/path
protoc my.proto --go_out=/some/absolute/path