问题描述
我最熟悉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
。