英文:
How to make go build work with nested directories
问题
在学习Go的过程中,我尝试创建自己的库。这是我所做的:在我的$GOPATH/src目录下,我有两个文件夹:mylibs
和test
。test
文件夹中有一个名为test.go
的文件,内容如下:
package test
import "mylibs/hi/saysHi"
func main() {
saysHi.SayHi()
}
mylibs
文件夹中包含一个名为hi
的文件夹,里面有一个名为saysHi.go
的文件,内容如下:
package saysHi
import "fmt"
func SayHi() {
fmt.Printf("Hi\n")
}
因此,目录结构如下:
- GOPATH/src
-
- test
-
-
- test.go
-
-
- mylibs
-
-
- hi
-
-
-
-
- saysHi.go
-
-
问题是,当我尝试编译test
时,它报错说:
cannot find package "mylibs/hi/saysHi" in any of:
[...]
$GOPATH/src/mylibs/hi/saysHi (from $GOPATH)
我故意将目录结构设置得比必要的深。如果我将saysHi.go
放在$GOPATH/saysHi/saysHi.go
的更简单的目录结构中,那么它可以工作。
但我不明白为什么这样不起作用。有什么想法吗?
英文:
In the process of learning go I was playing around with making my own libraries. Here is what I did: in my $GOPATH/src I have two folders: mylibs
and test
. The test
folder has a file called test.go
which contains
package test
import "mylibs/hi/saysHi"
func main() {
saysHi.SayHi()
}
The mylibs
folder contains another folder called hi
, which has a file called saysHi.go
containing:
package saysHi
import "fmt"
func SayHi() {
fmt.Printf("Hi\n")
}
So the directory structure looks like this:
- GOPATH/src
-
- test
-
-
- test.go
-
-
- mylibs
-
-
- hi
-
-
-
-
- saysHi.go
-
-
The problem is that when I try to compile test
it complains saying
cannot find package "mylibs/hi/saysHi" in any of:
[...]
$GOPATH/src/mylibs/hi/saysHi (from $GOPATH)
I have deliberately made the directory structure deeper than necessary. If I make a simpler directory structure where I place saysHi.go
in $GOPATH/saysHi/saysHi.go
then it works.
But I don't see a reason for why this wouldn't work. Any ideas?
答案1
得分: 6
通常情况下,你的目录名应该与包名相匹配。所以如果你定义了
package saysHi
并且想要用以下方式导入它
import "mylibs/hi/saysHi"
你应该按照以下结构放置它:
- mylibs
-
- hi
-
-
- saysHi
-
-
-
-
- saysHi.go
-
-
.go
文件的名称对导入路径没有影响,所以你可以随意命名 .go
文件。
进一步解释一下,你使用的导入路径应该是包含包的目录的名称。但是,如果你在该目录内定义了一个不同的包名,你应该使用该名称来访问代码中的包。这可能会令人困惑,所以最好在理解它最好的使用方式之前避免使用它(提示:包版本控制)。
这会令人困惑,所以举个例子,如果你的包在以下路径中
- mylibs
-
- hi
-
-
- saysHi.go
-
并且在 saysHi.go
中定义了
package saysHi
那么在 test.go
中,你将使用以下方式导入它
import "mylibs/hi"
并且使用以下方式使用它
saysHi.SayHi()
注意,你使用最终目录为 hi
进行导入,但使用名称 saysHi
进行使用。
最后的注意事项
以防你不知道以下内容:你的测试文件名为 test.go
,如果它只是一个示例,而不是 saysHi.go
的实际测试文件,那么这是可以的。但是,如果它是一个包含 saysHi.go
的测试的文件,那么 Go 的标准做法是将文件命名为 saysHi_test.go
并将其放置在与 saysHi.go
相同的包中。
再多一点注意事项
我提到过你可以选择与目录名不同的包名。但实际上有一种编写代码的方式可以减少混淆:
import (
saysHi "mylibs/hi"
)
这样可以从 mylibs/hi
目录导入它,并且提醒读者在使用代码时应该使用 saysHi
,这样读者就不必去查看 mylibs/hi
的代码。
英文:
Generally speaking, your directory name should match the package name. So if you define
package saysHi
and want to import it with
import "mylibs/hi/saysHi"
you should place it in a structure like this:
- mylibs
-
- hi
-
-
- saysHi
-
-
-
-
- saysHi.go
-
-
The name of the .go
file(s) inside the package makes no difference to the import path, so you could call the .go
file anything you like.
To explain it a bit further, the import path you use should be the name of the directory containing the package. But, if you define a different package name inside that directory, you should use that name to access the package inside the code. This can be confusing, so it's best to avoid it until you understand where it's best used (hint: package versioning).
It gets confusing, so for example, if you had your package in the path
- mylibs
-
- hi
-
-
- saysHi.go
-
And inside saysHi.go
defined,
package saysHi
Then in test.go you will import it with
import "mylibs/hi"
And use it with
saysHi.SayHi()
Notice how you import it with the final directory being hi
, but use it with the name saysHi
.
Final note
Just in case you didn't know the following: your test file is called test.go
, and that's fine, if it's just as an example, and not an actual test file for saysHi.go
. But if it is/were a file containing tests for saysHi.go
, then the accepted Go standard is to name the file saysHi_test.go
and place it inside the same package alongside saysHi.go
.
One more final note
I mentioned how you are allowed to choose a different package name from the directory name. But there is actually a way to write the code so that it's less confusing:
import (
saysHi "mylibs/hi"
)
Would import it from the mylibs/hi
directory, and make a note of the fact that it should be used with saysHi
, so readers of your code understand that without having to go look at the mylibs/hi
code.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论