0

按照 gRPC 官方网站上的 Quick Start gRPC Go 指南,它有一个步骤要求用户使用以下命令重新编译更新的 .proto 文件:

$ protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld/helloworld.proto

我对“人工编写的”Go 代码如何使用新编译的 protobuf 文件感到有些困惑。

在示例“人工编写的”Go 代码中,他们使用以下导入引用 protobuf 代码:

pb "google.golang.org/grpc/examples/helloworld/helloworld"

protoc不更新这个包,而是更新helloworld/helloworld.proto运行命令所在的同一目录中的包。命令如何protoc确保“人工编写”的 Go 代码使用新编译的 protobuf 代码?

4

1 回答 1

1

我发现这是 Protobufs(和 gRPC)更令人困惑的方面之一。

我认为要解决的问题是 Protobufs 需要:

  1. 允许命名空间范围服务|消息到例如 DNS 域
  2. 支持多种编程语言(以不同的方式实现命名空间)。

protoc具有允许v1/api使用 protobuf 选项(例如)将例如 protobuf 的包(例如)映射到特定于语言的命名空间的选项go_package。请参阅Go为 Golang 生成的代码。

这在使用 Go Modules 时稍微复杂一些,但总而言之,您遇到的可能是上述情况的某种(意外)组合,示例代码假定一个模块名称,并protoc建立在另一个模块名称的假设之上。

TL;DR 更新代码的模块引用以反映正确生成的pb路径。如果生成代码位于错误的位置,您只需将其移动到正确的子目录(路径),但最好更新您的protoc命令以将文件生成到正确的目录。

例子

something.proto

syntax = "proto3";

package v1alpha1;

option go_package = "github.com/me/my-protos;v1alpha1";

注意 go_package将 proto 包别名为v1alpha1我想github.com/me/my-protos在 Golang 中引用的内容。

然后我生成:

MODULE="github.com/me/my-protos"
protoc \
--proto_path=. \
--go_out=./api/v1alpha1 \
--go_opt=module=${MODULE} \
--go-grpc_out=./api/v1alpha1 \
--go-grpc_opt=module=${MODULE} \
./something.proto

注意此示例也生成 gRPC 代码。它避免(!)为生成的代码protoc创建路径github.com/me/my-protos,因为我在该存储库中生成源代码。我只想要创建文件的相对路径./api/v1alpha

产生:

my-protos
├── something.proto
├── api
│   └── v1alpha1
│       ├── something_grpc.pb.go
│       └── something.pb.go
├── go.mod
├── go.sum
└── README.md

我可以导入:

import (
    pb "github.com/me/my-protos/api/v1alpha1"
)

注意从不同的仓库,我现在可以访问我的 protos 仓库,结合 reprogithub.com/me/my-project/api/v1alpha1和生成的位置来提供我想要的路径。

于 2021-06-14T18:43:49.250 回答