go - 尝试编写共享的 protobuf 定义

标签 go protocol-buffers

我正在尝试在共享 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

commonmessages 要么在一个包中,要么在两个包​​中。

让我们做两件事:

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 package github.com/rob-woerner/protos/some and common.pb.go is in the sub-package github.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`
}

如果您希望commonmessages位于同一个包中,那么您可以:

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/

相关文章:

go - 是否可以在不运行 go install 的情况下更新本地软件包?

go - 为什么 binary.Size() 返回 (-1)?

java - 为 Java 中现有的二进制协议(protocol)生成解析器

c - 如何序列化/反序列化 protobuf-c 中的枚举

arrays - 在 Go 中,如何对任何类型的 slice/数组/字符串进行分区?

go - 函数定义了未命名的参数,但调用者仍然传递值

golang : serving net. Conn 使用 gin 路由器

iphone - 关于 iPhone 上的 ProtocolBuffers

c# - 为什么枚举不使用 protobufs 反序列化?

go - 与protobuf相比,flatbuffer序列化性能慢