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 定義)——除非有特別強烈的理由不這樣做。
- 1 回答
- 0 關注
- 195 瀏覽
添加回答
舉報