protoc Go Package Command Local Overwrite?

huangapple go评论81阅读模式
英文:

protoc Go Package Command Local Overwrite?

问题

根据官方gRPC网站上的快速入门gRPC Go指南,有一步要求用户使用以下命令重新编译更新的.proto文件:

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

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

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

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

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

英文:

Following the Quick Start gRPC Go guide on the official gRPC website it has a step which asks the user to recompile the updated .proto file using this command:

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

I'm a little confused as to how the newly compiled protobuf files are consumed by the "human written" Go code.

In the example "human written" Go code they reference the protobuf code using the following import:

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

protoc does not update this package but instead updates the helloworld/helloworld.proto in the same directory that the command is run in. How does the protoc command ensure that the "human written" Go code consumes the newly compiled protobuf code?

答案1

得分: 1

我发现这是Protobuf(和gRPC)中较为混乱的一个方面之一。

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

  1. 允许使用命名空间将服务|消息限定在特定的DNS域中。
  2. 支持多种编程语言(这些语言对命名空间的实现方式不同)。

protoc有一些选项可以使用Protobuf选项(例如go_package)将protobuf的包v1/api重新映射到特定语言的命名空间。有关Golang的详细信息,请参阅Go生成的代码

当使用Go Modules时,这会稍微复杂一些,但总结起来,你可能遇到的问题是上述情况的某种(意外的)组合,示例代码假设一个模块名称,而protoc则基于不同的假设进行构建。

简而言之,更新代码的模块引用,以反映正确生成的pb路径。如果生成的代码放错了位置,你可以将其简单地移动到正确的子目录(路径)中,但最好更新protoc命令,将文件生成到正确的目录中。

示例

something.proto:

syntax = "proto3";

package v1alpha1;

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

然后使用以下命令生成代码:

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存储库github.com/me/my-project/api/v1alpha1,将仓库和生成的位置组合起来,得到我想要的路径。

英文:

I find this one of the more confusing aspects of Protobufs (and gRPC).

I think the issue being solved is that Protobufs need to:

  1. Permit namespacing to scope services|messages to e.g. DNS domains
  2. Support a myriad programming languages (which implement namespacing differently).

protochas options that permit (re)mapping of e.g. a protobuf's package v1/api to a language-specific namespace using protobuf options, e.g. go_package). See Go Generated Code for Golang.

This is slightly more complex when using Go Modules but, in summary, what you're experiencing is probably some (unexpected) combination of the above where, the sample code assumes one module name and protoc is building on the assumption of a different one.

TL;DR update the code's module reference to reflect the correctly generated pb path. If the generate code is in the wrong place, you can simply move it to the correct subdirectory (path) but it's better to update your protoc command to generate the files to the correct directory.

Example

something.proto:

syntax = "proto3";

package v1alpha1;

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

> NOTE go_package aliases the proto package v1alpha1 to what I want to reference as github.com/me/my-protos in Golang.

Then I generate with:

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

> NOTE This example generate gRPC code too. It avoids (!) protoc creating a path github.com/me/my-protos for the generated code because I'm generating the source in that repo. I just want the relative path ./api/v1alpha where the files will be created.

Which yields:

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

And I can import with:

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

> NOTE From a different repo, I can now access my protos repo github.com/me/my-project/api/v1alpha1 combining the repro and the generated location to give my desired path.

huangapple
  • 本文由 发表于 2021年6月14日 17:39:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/67967978.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定