为了账号安全,请及时绑定邮箱和手机立即绑定

从 GitHub 存储库导入 protobuf 文件

从 GitHub 存储库导入 protobuf 文件

Go
神不在的星期二 2023-03-07 16:40:23
我目前有两个 protobuf 回购协议:api 和timestamp:时间戳回购:- README.md- timestamp.proto- timestamp.pb.go- go.mod- go.sumapi回购:- 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"; // golangmessage 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文件中,我应该怎么做才能确保导入不会在我的下游存储库中中断?
查看完整描述

1 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

protobuf 没有远程导入路径的本机概念。因此导入路径必须相对于某些指定的本地文件系统基本路径(通过-I/指定--proto_path)。


选项1

通常,最简单的方法是为您的组织拥有一个包含 protobuf 定义的存储库——例如,一个名为acme-contract


.

└── protos

    └── acme

        ├── api

        │   └── data

        │       ├── dto1.proto

        │       └── dto2.proto

        └── timestamp

            └── timestamp.proto

你的 dto1.proto 看起来像:


syntax = "proto3";


package acme.api.data;


import "acme/timestamp/timestamp.proto";


message DTO1 {

  string id = 1;

  acme.timestamp.Timestamp timestamp = 2;

}

只要您生成与protos/此存储库目录相关的代码,就不会有问题。


选项 2

有多种选择,您可以继续将定义拆分到不同的存储库,但您无法真正逃避导入是文件系统相关的事实。


从历史上看,这可以通过手动克隆各种存储库和安排目录来处理,这样路径是相对的,或者通过使用-I指向可能有意或偶然包含原型文件的各种位置(例如在 $GOPATH 中)。这些策略最终往往会变得相当混乱且难以维护。


buf现在让事情变得更容易了。如果你有你的timestamp回购协议:


.

├── buf.gen.yaml

├── buf.work.yaml

├── gen

│   └── acme

│       └── timestamp

│           └── timestamp.pb.go

├── go.mod

├── go.sum

└── protos

    ├── acme

    │   └── timestamp

    │       └── timestamp.proto

    ├── buf.lock

    └── buf.yaml

timestamp.proto看起来像:


syntax = "proto3";


package acme.timestamp;


option go_package = "github.com/my-user/timestamp/gen/acme/timestamp";


message Timestamp {

  int64 unix = 1;

}

buf.gen.yaml看起来像:


version: v1

plugins:

  - name: go

    out: gen

    opt: paths=source_relative

  - name: go-grpc

    out: gen

    opt:

      - paths=source_relative

      - require_unimplemented_servers=false

  - name: grpc-gateway

    out: gen

    opt:

      - paths=source_relative

      - generate_unbound_methods=true

... 并且下面的所有内容gen/都是通过生成的buf generate。


然后在您的api存储库中:


.

├── buf.gen.yaml

├── buf.work.yaml

├── gen

│   └── acme

│       └── api

│           └── data

│               ├── dto1.pb.go

│               └── dto2.pb.go

└── protos

    ├── acme

    │   └── api

    │       └── data

    │           ├── dto1.proto

    │           └── dto2.proto

    ├── buf.lock

    └── buf.yaml

看起来buf.yaml像:


version: v1

name: buf.build/your-user/api

deps:

  - buf.build/your-user/timestamp

breaking:

  use:

    - FILE

lint:

  use:

    - DEFAULT

dto1.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 {

  string id = 1;

  acme.timestamp.Timestamp timestamp = 2;

}

和回购buf.gen.yaml中的一样timestamp。


通过生成的代码buf generate将取决于timestamp通过 Go 模块的存储库:


// Code generated by protoc-gen-go. DO NOT EDIT.

// versions:

//  protoc-gen-go v1.28.1

//  protoc        (unknown)

// source: acme/api/data/dto1.proto


package data


import (

    timestamp "github.com/your-user/timestamp/gen/acme/timestamp"

    protoreflect "google.golang.org/protobuf/reflect/protoreflect"

    protoimpl "google.golang.org/protobuf/runtime/protoimpl"

    reflect "reflect"

    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: v1

managed:

  enabled: true

  go_package_prefix:

    default: github.com/your-user/api-go/gen

plugins:

  - name: go

    out: gen

    opt: paths=source_relative

  - name: go-grpc

    out: gen

    opt:

      - paths=source_relative

      - require_unimplemented_servers=false

  - name: grpc-gateway

    out: gen

    opt:

      - paths=source_relative

      - generate_unbound_methods=true

然后,您需要为每个相应的回购生成代码(传送到 BSR):


$ buf generate buf.build/your-user/api

$ buf generate buf.build/your-user/timestamp

之后你应该为两者生成一些代码:


.

├── buf.gen.yaml

├── gen

│   └── acme

│       ├── api

│       │   └── data

│       │       ├── dto1.pb.go

│       │       └── dto2.pb.go

│       └── timestamp

│           └── timestamp.pb.go

├── go.mod

└── go.sum

并且导入将相对于当前模块:


// Code generated by protoc-gen-go. DO NOT EDIT.

// versions:

//  protoc-gen-go v1.28.1

//  protoc        (unknown)

// source: acme/api/data/dto1.proto


package data


import (

    timestamp "github.com/your-user/api-go/gen/acme/timestamp"

    protoreflect "google.golang.org/protobuf/reflect/protoreflect"

    protoimpl "google.golang.org/protobuf/runtime/protoimpl"

    reflect "reflect"

    sync "sync"

)


// <snip>

总而言之,我推荐选项 1——将你的 protobuf 定义整合到一个单一的存储库中(包括 vendoring 3rd party 定义)——除非有特别强烈的理由不这样做。


查看完整回答
反对 回复 2023-03-07
  • 1 回答
  • 0 关注
  • 94 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信