我正在尝试在共享 go 模块中创建共享 protobuf 定义,但我运气不佳。具体来说:
- 我想要模块 protos 中包含共享定义的 proto 文件。
- 模块 protos 中的其他 proto 文件将引用共享定义。
- 模块 protos-use 将引用模块 protos (通过 go.mod)
- 模块 protos-use go 代码将导入并使用模块 protos 中的定义
- 两个模块都存储在github.com
我无法使各种包名称保持一致。无论我使用什么,总会有东西失败。目前,模块 protos 没有任何错误,但 go mod tidy on module protos-use 失败。
模块原型(prototype)位于 https://github.com/rob-woerner/protos
模块原型(prototype)使用位于 https://github.com/rob-woerner/protos-use
我还没有找到解决这种情况的示例。如果我只是在各处复制共享的原型(prototype)定义,我就可以让它工作。最近的错误是:
$ 去修改整洁
go:查找包 github.com/rob-woerner/protos/messages
的模块
go:查找包 github.com/rob-woerner/protos/common
的模块
github.com/rob-woerner/protos-use/代码导入
github.com/rob-woerner/protos/common:找到模块 github.com/rob-woerner/protos@latest (XXX),但不包含包 github.com/rob-woerner/protos/common
github.com/rob-woerner/protos-use/代码导入
github.com/rob-woerner/protos/messages:找到模块 github.com/rob-woerner/protos@latest (XXX),但不包含包 github.com/rob-woerner/protos/messages
但我强调,我会遇到很多不同的错误,具体取决于我在十几个需要包名称的地方使用的包名称。
如果有人知道一个可行的示例,或者如果不支持此示例,我将不胜感激。
为了简洁起见,省略了代码片段
模块原型(prototype):
go.mod
生成文件
Protocol Buffer :
common.proto
messages.proto
铅:
common.pb.go
messages.pb.go
模块原型(prototype)使用:
go.mod
代码:
项目.go
模块原型(prototype):
go.mod:
模块原型(prototype)
转到1.16
需要 google.golang.org/protobuf v1.27.1
protobuf/common.proto:
封装通用;
选项 go_package = "github.com/rob-woerner/protos";
枚举 MyState { LOGGED_OUT = 0; }
protobuf/messages.proto:
导入“common.proto”;
打包消息;
选项 go_package = "github.com/rob-woerner/protos";
消息 MyRequest { common.MyState 状态 = 1; }
生成文件:
原型(prototype):
protoc --proto_path=protobuf --go_out=plugins=grpc:pb --go_opt=module=github.com/rob-woerner/protos protobuf/*.proto
模块原型(prototype)使用:
go.mod:
模块 github.com/rob-woerner/protos-use
转到1.16
要求(
github.com/rob-woerner/protos 最新
)
代码/project.go:
封装代码
导入(
“github.com/rob-woerner/protos/common”
“github.com/rob-woerner/protos/messages”
)
func MyFunc() messages.MyMessage {
返回 messages.MyMessage { state: common.MyState_LOGGED_OUT}
}
最佳答案
这对于 protobuf 来说是一个挑战,并且记录很少。
我认为,部分复杂性在于 protobuf 维护者正在尝试解决可能使用的无数运行时和包的问题。
如果我正确理解你的问题,那么你所拥有的,protos-use
正在挣扎,因为 code/product.go
应该:
import (
"github.com/rob-woerner/protos/pb/common" // /pb/
...
)
我有一个工作机制,我将尝试将其应用于您的机制。我认为对 common
的引用不是您的问题,而是整体结构和模块与包导入的问题:
github.com/foo/protos
github.com/bar/app
在 foo/protos
中,我的根目录中有 *.proto
文件(但这只是一个约定,不一定如此):
example.proto
syntax = "proto3";
package baz;
option go_package = "github.com/foo/protos;baz";
service Some {...}
NOTE The
;baz
this describe the eventual Go package name (baz
) of the generated code. It need not match the the repo name (protos
) and I don't want this because (see below), I'm putting the generated code in a non-root directory (/some/baz
)
然后:
MODULE="github.com/foo/protos"
protoc \
--include_imports \
--include_source_info \
--proto_path=. \
--descriptor_set_out=foo.pb \
--go_out=./some/baz \
--go_opt=module=${MODULE} \
--go-grpc_out=./some/baz \
--go-grpc_opt=module=${MODULE} \
./*.proto
NOTE This will give us a package name of
github.com/foo/protos/some/baz
这将产生:
.
├── example.proto
├── some
│ └── baz
│ ├── example_grpc.pb.go
│ └── example.pb.go
├── go.mod
├── go.sum
└── protoc-3.17.3-linux-x86_64
然后,从 bar/app
中,我有:
go.mod
:
module github.com/bar/app
go 1.16
require (
github.com/foo/protos v0.0.1
...
)
并且,在该模块中,我为导入别名:
package main
import (
...
pb "github.com/foo/protos/some/baz"
)
func main() {
...
pb.RegisterSomeServer(grpcServer, ...)
更新
NOTE Responding to the comment thread
common
和 messages
要么在一个包中,要么在两个包中。
让我们做两件事:
common.proto
:
syntax = "proto3";
package common;
option go_package = "github.com/rob-woerner/protos/common;common";
enum MyState { LOGGED_OUT = 0; }
messages.proto
:
syntax = "proto3";
package messages;
import "common.proto";
option go_package = "github.com/rob-woerner/protos/messages;messages";
message MyRequest { common.MyState state = 1; }
NOTE Because we want 2 packages, we need to give the protos (!) unique
package
,go_package
names./protos/common;common
. Although we could have./protos/common;freddie
, the issue is that the path must be unique to give a unique package.
然后:
MODULE="github.com/rob-woerner/protos"
protoc \
--proto_path=. \
--go_out=./some \
--go_opt=module=${MODULE} \
--go-grpc_out=./some \
--go-grpc_opt=module=${MODULE}
NOTE The use of
some
here is solely to ensure that the generated code ends up aggregated by some package (some
) below the repo(==module) root. You can remove/some
if you want the packages directly beneath the module root.
产量:
some
├── common
│ └── common.pb.go
└── messages
└── messages.pb.go
NOTE
some
becomes the root packagegithub.com/rob-woerner/protos/some
andcommon.pb.go
is in the sub-packagegithub.com/rob-woerner/protos/some/common
所以,我们现在可以:
main.go
:
package main
import (
"github.com/rob-woerner/protos/some/common"
"github.com/rob-woerner/protos/some/messages"
)
func main() {
rqst := messages.MyRequest{
state: common.MyState_LOGGED_OUT,
}
// do something with `rqst`
}
如果您希望common
和messages
位于同一个包中,那么您可以:
package protos;
option go_package = "github.com/rob-woerner/protos;protos`;
还有:
message MyRequest { MyState state = 1; } // Now in same package
然后:
MODULE="github.com/rob-woerner/protos"
protoc \
--proto_path=. \
--go_out=./protos \
--go_opt=module=${MODULE} \
--go-grpc_out=./protos \
--go-grpc_opt=module=${MODULE}
NOTE In this case, we need
_out=./protos
so that the generated files get put under the correct package (protos
main.go
:
package main
import (
pb "github.com/rob-woerner/protos"
)
func main() {
rqst := pb.MyRequest{
state: pb.MyState_LOGGED_OUT,
}
// do something with `rqst`
}
唷!我说这很有挑战性;-)
关于go - 尝试编写共享的 protobuf 定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68627269/