在Go打包,导入和原型上为我学习 导入声明 protoc的用法

问题描述

我最熟悉Python和bazel构建环境。我正在尝试在Go中重写部分代码,并且正努力使原型导入正确对齐。

github.com/djhedges/exit_speed/gps.proto中,我像这样设置了go_package

option go_package = "github.com/djhedges/exit_speed/gps_go_proto";

添加了reflector.proto,它可以导入gps.proto并重用其中定义的某些消息。

import "gps.proto";

我用{p>编译gps.proto

protoc -I ./ --go_out=./ --go_opt=paths=source_relative --python_out ./ gps.proto

并使用{p>编译reflector.proto

LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1 python3 -m grpc_tools.protoc -I ./ --go_out=./ --go_opt=paths=source_relative --python_out ./ --grpc_python_out ./ reflector.proto

最后在exit_speed / reflector.go中,我尝试使用以下方式导入gps_go_proto

import gpspb "github.com/djhedges/exit_speed/gps_go_proto"

哪个错误

go: finding github.com/djhedges/exit_speed/gps_go_proto latest
reflector.go:21:2: unkNown import path "github.com/djhedges/exit_speed/gps_go_proto": cannot find module providing package github.com/djhedges/exit_speed/gps_go_proto

如果可能的话,我希望将gps.proto保留在根目录中,因为我已经将protos登录到数据文件中,并且我相信移动此操作会破坏proto的解析。我想我可以写一个迁移脚本。

对于如何使用不同的go包和导入设置多个原型,我也感到困惑。包裹必须有一个专用文件夹吗?

解决方法

如果我理解正确的软件包,则软件包名称必须映射到目录。将1 248956422 2051 2 242193529 1244 7 159345973 917 X 156040895 850 Y 56887902 47 22 50818468 444 21 46709983 233 KI270728_1 1872759 6 KI270727_1 448248 4 KI270726_1 43739 2 GL000009_2 201709 1 KI270322_1 21476 0 GL000226_1 15008 0 KI270311_1 12399 0 KI270366_1 8320 0 KI270511_1 8127 0 KI270448_1 7992 0 更改为--go_out=./似乎可以解决我的问题,而不必移动原始文件。这确实意味着我还有一些其他目录,但这似乎还可以。

,

Go Specification import section说:

导入声明

一个导入声明指出包含该声明的源文件取决于导入的软件包(§Program initialization and execution)的功能,并允许访问该软件包的exported标识符。导入将命名用于访问的标识符(PackageName)和用于指定要导入的软件包的ImportPath。

ImportDecl       = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec       = [ "." | PackageName ] ImportPath .
ImportPath       = string_lit .

(在此处剪断,我断开了一些链接;使用第一个链接获取包含链接的文本)。字符串文字很熟悉:

import "github.com/..."

part; PackageName或点是可选的。返回文字:

ImportPath的解释取决于实现,但是它通常是已编译软件包完整文件名的子字符串,并且可能与已安装软件包的存储库有关。

在您自己的答案中,添加:

如果我理解正确的软件包,则软件包名称必须映射到目录。

那不是不必要。由实现决定字符串文字的含义。通常,Go构建系统会使用此路径找到一个充满文件的目录。它还可以使用版本控制系统(例如Git)来填充充满文件的目录,以便编译器可以找到它们。

有些令我惊讶的事情,但最终还是很有意义的(规范中对做了的描述)是:在package clause中找到的程序包名称:

package somename
某些导入文件顶部的

声明有时是无关紧要的。当然,一个包含实现包x的文件的目录将全部带有package x。但这是行中的y标识符:

import y "path/to/x"
您的包中的

提供您用于访问导出的标识符的名称。即使包本身显示y,您在此处使用的名称(包的名称为y)也为package x。实际上,软件包x中的package子句只是推荐名称x,以便您可以编写:

import "path/to/x"

如果您想将它们称为x.Thing

也不需要字符串文字提及x:也许所有文件都位于通过path/to/z找到的东西中,而您写:

import "path/to/z"

然后(仍然)写入x.Thing,因为path/to/z/*.go中的文件建议使用x作为程序包名称。

protoc的用法

无论上述内容如何,​​protobuf Go生成器都会在生成的name*.pb.go* Go代码中打印import指令。该import指令将显示为:

import "some/path/here"

您可以使用option go_package指定字符串文字。 protobuf编译器不需要 对此进行解释。但是,作为the documentation notes,这些name.pb.go文件本身将被放置到某个目录中。当然,它们还将包含package pkg行。

  • 每个输出文件的位置取决于您是否使用--go_opt=paths=source_relative。如果您这样做,则go_package选项字符串在这里变得无关紧要。

  • .pb.go文件生成器将使用go_package选项字符串,剥离所有内容(包括最后一个斜杠),并将其余的字符串用于package行。 / p>

second 点表示,无论Go系统本身做什么,如何找到这些文件以及如何编写自己的import建议包名称​​ in 中的那些文件将成为go_package选项中所有内容的最后一个组成部分。因此,从某种意义上说,您真正需要的只是最后一个组件。但是,如果您的Go实施需要的还更多,那么您可以提供更多。

第一点表示如果您使用--go_opt=paths=source_relative,则{{ 1}}选项很重要:Go生成器将尝试使用该字符串来生成输出文件。因此,如果您的Go实施需要更多功能,并且您确实提供了更多功能,并且与您想要的输出文件名不匹配,那么您肯定需要go_package