【问题标题】:Protobuf compiler for Go structs not generating the right package name for imports?Go 结构的 Protobuf 编译器没有为导入生成正确的包名称?
【发布时间】:2020-03-04 18:19:57
【问题描述】:

考虑以下示例项目,其 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;
}

我已经生成了.pb.go 文件,在proto/ 目录中运行

protoc book/book.proto --go_out=../gen/go

protoc author/author.proto --go_out=../gen/go

问题是authorbook.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),但这样做似乎不会改变生成的代码)。

【问题讨论】:

    标签: go protocol-buffers go-modules protoc


    【解决方案1】:

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


    如果您的 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-01
      • 2012-01-05
      • 2011-03-14
      • 1970-01-01
      • 2018-04-24
      • 2021-03-20
      • 2021-01-16
      • 2011-04-07
      相关资源
      最近更新 更多