如何使go build与嵌套目录一起工作

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

How to make go build work with nested directories

问题

在学习Go的过程中,我尝试创建自己的库。这是我所做的:在我的$GOPATH/src目录下,我有两个文件夹:mylibstesttest文件夹中有一个名为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.

huangapple
  • 本文由 发表于 2016年2月22日 10:24:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/35544843.html
匿名

发表评论

匿名网友

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

确定