protoC语言 -go_opt=paths=source_relative vs --go-grpc_opt=paths



我很难弄清楚protoc命令并去插件。

两者有什么区别:

protoc 
# Directory where you want the compiler to write your Go output.
--go_out=.
# vs ?
--go_opt=paths=source_relative
# vs ?
--go-grpc_out=.
# vs ?
--go-grpc_opt=paths=source_relative

如果--go_opt生成

  • <name>.pb.go文件

--go-grpc_opt生成

  • <name>_grpc.pb.go文件

为什么还要--go_out

你能对 protoc 有所了解吗 - 文档没有说任何关于--go-grpc_opt的事情?

而且protoc -h甚至没有将围棋列为OUT_DIR?

注意:我使用此文档安装

为什么还要有--go_out?

因此,这里要了解的是,gRPC 与协议缓冲区不同,gRPC 使用协议缓冲区,但还有其他框架也在使用它们。因此,我们需要同时生成两者。

现在,为了生成与协议缓冲区相关的代码,您需要使用您提到的--go_out。 但是对于 gRPC 代码,您需要使用--go-grpc_out.

和 --

go-grpc_opt 生成 _grpc.pb.go 文件

不,--go-grpc_out做到了。

你能对 protoc 进行一些说明吗 - 文档不会保留任何关于 --go-grpc_opt 的内容?

然后,在生成代码之前,您可以传递一些选项,这就是--go_opt--go-grpc_opt的用途。第一个传递 Protobuf 生成的选项,第二个传递 gRPC 生成的选项。选项非常晦涩难懂,并且没有所有选项的官方列表,但是您使用了source_relative(告诉protoc使用相对路径)作为路径,并且还有module选项(帮助protoc知道go模块名称以在正确的文件夹中生成)

而且 protoc -h 甚至没有将 go 列为OUT_DIR?

最后,protoc 不正式支持 Go 作为输出,您需要安装一个外部插件,这就是为什么protoc -h不显示--go_out的原因。可以在此处找到相关讨论。

protoc

编译器支持不同的标志或选项,您在命令行上使用的标志决定了生成的 go 代码的放置位置。

这些标志的官方文档(至少对于paths=source_relativemodule=$PREFIX)不是很清楚,可能很难。

路径=source_relative

这是官方文档所说的

如果指定了 paths=source_relative 标志,则输出文件为 放置在与输入文件相同的相对目录中。例如 输入文件 protos/buzz.proto 生成一个输出文件,网址为 Protos/buzz.pb.go.

上述陈述一开始可能会令人困惑且难以理解,因为 它没有提供文件在磁盘上放置方式的完整上下文和文件夹布局。

这是我的理解,当使用此标志时,编译器会在指定的目录中生成 go 代码--go_out并确保生成的go代码的目录树结构 文件与原型文件的目录树结构匹配。词源 在这里很重要,因为它可以根据--proto_path的值而变化

假设我们有以下目录结构

❯ tree
.
├── go.mod
├── go.sum
└── src
└── protos
├── baz
│   └── bar.proto
└── foo.proto
4 directories, 4 files

这是protoc命令的一般语法

protoc --proto_path=<IMPORT_DIRECTORY> --go_out=. --go_opt=paths=source_relative <ONE_OR_MORE_SOURCE_PROTO_FILES>

现在让我们考虑以下示例

#1

❯ protoc --proto_path=src/protos --go_out=. --go_opt=paths=source_relative foo.proto baz/bar.proto
❯ ls
baz       foo.pb.go go.mod    go.sum    src
~/development/personal/craftup/go-grpc/proto-buffers
❯ ls -R baz
bar.pb.go

在上面的例子中,我们通过设置--proto_path=src/protos指定了导入目录 这使得源原型文件的实际路径要foo.protobaz/bar.proto,因此生成的pb文件被放置在当前 目录 (--go_out=.) 作为foo.pb.gobar/baz.pb.go

现在让我们将上述命令中的--proto_path更改为src,看看有什么好玩的。

**# 2**
❯ protoc --proto_path=src --go_out=. --go_opt=paths=source_relative protos/foo.proto protos/bar/baz.proto
❯ ls -R src
protos
src/protos:
baz       foo.proto
src/protos/baz:
bar.proto

这次创建了一个新的protos目录,并放置了生成的 go 文件 在里面,为什么?因为这次我们将导入路径更改为--proto-path=src源原型文件的路径更改为protos/foo.protoprotos/baz/bar.proto

#3

现在让我们最终在这里混合--go_out标志,看看会发生什么

❯ mkdir out
❯ protoc --proto_path=src --go_out=out --go_opt=paths=source_relative protos/foo.proto protos/bar/baz.proto
❯ ls -R out
protos
out/protos:
baz       foo.pb.go
out/protos/baz:
bar.pb.go

这与上一个示例完全相同,只是我们提供了一个自定义目录来保存生成的代码。

模块=$PREFIX

如果指定了 module=$PREFIX 标志,则输出文件将放在 以 Go 包的导入路径命名的目录,但具有 从输出文件名中删除了指定的目录前缀。为 例如,输入文件 protos/buzz.proto 的 Go 导入路径为 example.com/project/protos/fizz 和 example.com/project 指定为 模块前缀在Protos/Fizz/buzz.pb.go上生成输出文件。 在模块路径之外生成任何 Go 包会导致 错误。此模式对于直接输出生成的文件很有用 进入 Go 模块。

让我们看看这个以及实际操作,考虑以下原型文件 包含以下内容的地点src/baz/bar.proto

syntax = "proto3";
package bar;
option go_package = "github.com/rbhanot/proto-buffers-practise/bar";
message GreetBar {
string name = 1;
}
❯ protoc --proto_path=src --go_out=. --go_opt=module=github.com/rbhanot/proto-buffers-practise protos/foo.proto protos/baz/bar.proto
❯ ls
bar    foo    go.mod go.sum src
~/development/personal/craftup/go-grpc/proto-buffers
❯ ls -R foo bar
bar:
bar.pb.go
foo:
foo.pb.go

让我们看看这里发生了什么,编译器从中删除了模块前缀(github.com/rbhanot/proto-buffers-practise) 在 proto 文件中指定的go_package,然后在当前目录中创建了包目录(--go_out=.) 以go_package选项中的其余路径命名,这些路径被foobar,并转储其中的代码文件。

现在让我们更改go_package = "github.com/rbhanot/proto-buffers-practise/src";并运行与上面相同的命令

❯ protoc --proto_path=src --go_out=out --go_opt=module=github.com/rbhanot/proto-buffers-practise protos/foo.proto protos/baz/bar.proto
❯ ls
go.mod go.sum out    src
~/development/personal/craftup/go-grpc/proto-buffers
❯ ls out/src
bar.pb.go foo.pb.go

这次我们看到 go 代码是在out/src目录中生成的。

我希望这能让事情更清楚(至少对我来说是这样)这些标志的行为方式。

相关内容

最新更新