从 GitHub 存储库导入 protobuf 文件

我目前有两个 protobuf 回购协议:api 和timestamp:


时间戳回购:


- README.md

- timestamp.proto

- timestamp.pb.go

- go.mod

- go.sum

api回购:


- README.md

- protos/

  - dto1.proto

  - dto2.proto

目前,timestamp包含对我想在其中使用的时间戳对象的引用api,但我不确定导入应该如何工作或者我应该如何修改编译过程来处理这个问题。使这个过程复杂化的是,apirepo 被编译为一个单独的、下游的 Go 的 repo,名为api-go.


例如,考虑dto1.proto:


syntax = "proto3";

package api.data;


import "<WHAT GOES HERE?>";


option go_package = "github.com/my-user/api/data"; // golang


message DTO1 {

    string id = 1;

    Timestamp timestamp = 2;

}

我的编译命令是这样的:


find $GEN_PROTO_DIR -type f -name "*.proto" -exec protoc \

    --go_out=$GEN_OUT_DIR --go_opt=module=github.com/my-user/api-go \

    --go-grpc_out=$GEN_OUT_DIR --go-grpc_opt=module=github.com/my-user/api-go \

    --grpc-gateway_out=$GEN_OUT_DIR --grpc-gateway_opt logtostderr=true \

    --grpc-gateway_opt paths=source_relative --grpc-gateway_opt 

    generate_unbound_methods=true \{} \;

timestamp假设我对要编译成的每种编程语言都有一个定义api,我将如何将其导入到.proto文件中,我应该怎么做才能确保导入不会在我的下游存储库中中断?


神不在的星期二
浏览 97回答 1
1回答

海绵宝宝撒

protobuf 没有远程导入路径的本机概念。因此导入路径必须相对于某些指定的本地文件系统基本路径(通过-I/指定--proto_path)。选项1通常,最简单的方法是为您的组织拥有一个包含 protobuf 定义的存储库——例如,一个名为acme-contract.└── protos&nbsp; &nbsp; └── acme&nbsp; &nbsp; &nbsp; &nbsp; ├── api&nbsp; &nbsp; &nbsp; &nbsp; │&nbsp; &nbsp;└── data&nbsp; &nbsp; &nbsp; &nbsp; │&nbsp; &nbsp; &nbsp; &nbsp;├── dto1.proto&nbsp; &nbsp; &nbsp; &nbsp; │&nbsp; &nbsp; &nbsp; &nbsp;└── dto2.proto&nbsp; &nbsp; &nbsp; &nbsp; └── timestamp&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └── timestamp.proto你的 dto1.proto 看起来像:syntax = "proto3";package acme.api.data;import "acme/timestamp/timestamp.proto";message DTO1 {&nbsp; string id = 1;&nbsp; acme.timestamp.Timestamp timestamp = 2;}只要您生成与protos/此存储库目录相关的代码,就不会有问题。选项 2有多种选择,您可以继续将定义拆分到不同的存储库,但您无法真正逃避导入是文件系统相关的事实。从历史上看,这可以通过手动克隆各种存储库和安排目录来处理,这样路径是相对的,或者通过使用-I指向可能有意或偶然包含原型文件的各种位置(例如在 $GOPATH 中)。这些策略最终往往会变得相当混乱且难以维护。buf现在让事情变得更容易了。如果你有你的timestamp回购协议:.├── buf.gen.yaml├── buf.work.yaml├── gen│&nbsp; &nbsp;└── acme│&nbsp; &nbsp; &nbsp; &nbsp;└── timestamp│&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└── timestamp.pb.go├── go.mod├── go.sum└── protos&nbsp; &nbsp; ├── acme&nbsp; &nbsp; │&nbsp; &nbsp;└── timestamp&nbsp; &nbsp; │&nbsp; &nbsp; &nbsp; &nbsp;└── timestamp.proto&nbsp; &nbsp; ├── buf.lock&nbsp; &nbsp; └── buf.yamltimestamp.proto看起来像:syntax = "proto3";package acme.timestamp;option go_package = "github.com/my-user/timestamp/gen/acme/timestamp";message Timestamp {&nbsp; int64 unix = 1;}buf.gen.yaml看起来像:version: v1plugins:&nbsp; - name: go&nbsp; &nbsp; out: gen&nbsp; &nbsp; opt: paths=source_relative&nbsp; - name: go-grpc&nbsp; &nbsp; out: gen&nbsp; &nbsp; opt:&nbsp; &nbsp; &nbsp; - paths=source_relative&nbsp; &nbsp; &nbsp; - require_unimplemented_servers=false&nbsp; - name: grpc-gateway&nbsp; &nbsp; out: gen&nbsp; &nbsp; opt:&nbsp; &nbsp; &nbsp; - paths=source_relative&nbsp; &nbsp; &nbsp; - generate_unbound_methods=true... 并且下面的所有内容gen/都是通过生成的buf generate。然后在您的api存储库中:.├── buf.gen.yaml├── buf.work.yaml├── gen│&nbsp; &nbsp;└── acme│&nbsp; &nbsp; &nbsp; &nbsp;└── api│&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└── data│&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;├── dto1.pb.go│&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└── dto2.pb.go└── protos&nbsp; &nbsp; ├── acme&nbsp; &nbsp; │&nbsp; &nbsp;└── api&nbsp; &nbsp; │&nbsp; &nbsp; &nbsp; &nbsp;└── data&nbsp; &nbsp; │&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;├── dto1.proto&nbsp; &nbsp; │&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└── dto2.proto&nbsp; &nbsp; ├── buf.lock&nbsp; &nbsp; └── buf.yaml看起来buf.yaml像:version: v1name: buf.build/your-user/apideps:&nbsp; - buf.build/your-user/timestampbreaking:&nbsp; use:&nbsp; &nbsp; - FILElint:&nbsp; use:&nbsp; &nbsp; - DEFAULTdto1.proto看起来像:syntax = "proto3";package acme.api.data;import "acme/timestamp/timestamp.proto";option go_package = "github.com/your-user/api/gen/acme/api/data";message DTO1 {&nbsp; string id = 1;&nbsp; acme.timestamp.Timestamp timestamp = 2;}和回购buf.gen.yaml中的一样timestamp。通过生成的代码buf generate将取决于timestamp通过 Go 模块的存储库:// Code generated by protoc-gen-go. DO NOT EDIT.// versions://&nbsp; protoc-gen-go v1.28.1//&nbsp; protoc&nbsp; &nbsp; &nbsp; &nbsp; (unknown)// source: acme/api/data/dto1.protopackage dataimport (&nbsp; &nbsp; timestamp "github.com/your-user/timestamp/gen/acme/timestamp"&nbsp; &nbsp; protoreflect "google.golang.org/protobuf/reflect/protoreflect"&nbsp; &nbsp; protoimpl "google.golang.org/protobuf/runtime/protoimpl"&nbsp; &nbsp; reflect "reflect"&nbsp; &nbsp; sync "sync")// <snip>请注意,如果对依赖项进行了更改,您需要确保 buf 和 Go 模块保持相对同步。选项 3如果您不想利用 Go 模块来导入生成的 pb 代码,您也可以使用与 类似的设置Option 2,而是将所有代码生成到一个单独的存储库中(听起来与您现在所做的类似) . 这最容易通过使用buf托管模式来实现,这将本质上使其不需要 + 忽略任何go_modules指令。在api-go:.├── buf.gen.yaml├── go.mod└── go.sum含有buf.gen.yaml:version: v1managed:&nbsp; enabled: true&nbsp; go_package_prefix:&nbsp; &nbsp; default: github.com/your-user/api-go/genplugins:&nbsp; - name: go&nbsp; &nbsp; out: gen&nbsp; &nbsp; opt: paths=source_relative&nbsp; - name: go-grpc&nbsp; &nbsp; out: gen&nbsp; &nbsp; opt:&nbsp; &nbsp; &nbsp; - paths=source_relative&nbsp; &nbsp; &nbsp; - require_unimplemented_servers=false&nbsp; - name: grpc-gateway&nbsp; &nbsp; out: gen&nbsp; &nbsp; opt:&nbsp; &nbsp; &nbsp; - paths=source_relative&nbsp; &nbsp; &nbsp; - generate_unbound_methods=true然后,您需要为每个相应的回购生成代码(传送到 BSR):$ buf generate buf.build/your-user/api$ buf generate buf.build/your-user/timestamp之后你应该为两者生成一些代码:.├── buf.gen.yaml├── gen│&nbsp; &nbsp;└── acme│&nbsp; &nbsp; &nbsp; &nbsp;├── api│&nbsp; &nbsp; &nbsp; &nbsp;│&nbsp; &nbsp;└── data│&nbsp; &nbsp; &nbsp; &nbsp;│&nbsp; &nbsp; &nbsp; &nbsp;├── dto1.pb.go│&nbsp; &nbsp; &nbsp; &nbsp;│&nbsp; &nbsp; &nbsp; &nbsp;└── dto2.pb.go│&nbsp; &nbsp; &nbsp; &nbsp;└── timestamp│&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└── timestamp.pb.go├── go.mod└── go.sum并且导入将相对于当前模块:// Code generated by protoc-gen-go. DO NOT EDIT.// versions://&nbsp; protoc-gen-go v1.28.1//&nbsp; protoc&nbsp; &nbsp; &nbsp; &nbsp; (unknown)// source: acme/api/data/dto1.protopackage dataimport (&nbsp; &nbsp; timestamp "github.com/your-user/api-go/gen/acme/timestamp"&nbsp; &nbsp; protoreflect "google.golang.org/protobuf/reflect/protoreflect"&nbsp; &nbsp; protoimpl "google.golang.org/protobuf/runtime/protoimpl"&nbsp; &nbsp; reflect "reflect"&nbsp; &nbsp; sync "sync")// <snip>总而言之,我推荐选项 1——将你的 protobuf 定义整合到一个单一的存储库中(包括 vendoring 3rd party 定义)——除非有特别强烈的理由不这样做。
打开App,查看更多内容
随时随地看视频慕课网APP