go - Go 结构的 Protobuf 编译器没有为导入生成正确的包名称?

标签 go protocol-buffers go-modules protoc

考虑以下带有 Go 模块的示例项目 github.com/kurtpeek/proto-example和以下目录结构(.proto 目录中的 proto 文件和 gen/go 中生成的 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;
}

我已经生成了 .pb.go文件,在 proto/目录,运行
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"
)

如何让 Protobuf 编译器“知道”生成代码所在的 Go 模块?

(我怀疑我需要指定 option go_package(参见 https://developers.google.com/protocol-buffers/docs/gotutorial),但这样做似乎不会改变生成的代码)。

最佳答案

您快到了!我怀疑你可能会被相对路径咬伤......

如果您的 proto 文件以这样的开头:

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 - Go 结构的 Protobuf 编译器没有为导入生成正确的包名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60532407/

相关文章:

go - 从 Go 代码构建 Docker 镜像

go - 如何使用带有环境变量或相对路径的替换指令

testing - Golang 测试脚本可以发出警告而不是错误吗?

go - 在 golang 中将 []*string 转换为 []string

c# - C++ 中的 Google ProtoBuf 与 C# 中的 Protobuf-net 聊天(UDP)

go - 如何正确描述 proto 文件?

git - 去使用 ssh 而不是 https(不在 github 上)

go - 有没有更简单的方法来更新本地 Go 包

go mod vendors 旧版本的依赖

rust - 如何确定由 include! 包含的 rust-protobuf 生成的 .rs 文件中的消息宏观