查看此实验。
~/go/src$ tree -F
.
├── 1-foodir/
│ └── 2-foofile.go
└── demo.go
1 directory, 2 files
~/go/src$ cat demo.go
package main
import (
"fmt"
"1-foodir"
)
func main() {
fmt.Println(foopkg.FooFunc())
}
~/go/src$ cat 1-foodir/2-foofile.go
package foopkg
func FooFunc() string {
return "FooFunc"
}
~/go/src$ GOPATH=~/go go run demo.go
FooFunc
我以为我们总是导入一个包名。但是上面的例子
显示我们实际上导入了一个包目录名称(“1-foodir”
)
但是在该包中调用导出的名称时,我们使用
Go 文件中声明的包名称 (foopkg.FooFunc
)。
这对于像我这样来自 Java 和 Python 世界的初学者来说是令人困惑的, 其中目录名称本身是用于限定的包名称 包中定义的模块/类。
为什么我们使用 import
语句的方式和
在 Go 中引用包中定义的名称?你能解释一下规则吗
关于 Go 的这些事情背后?
最佳答案
如果你说的是真的,那么你的函数调用实际上是 1-foodir.FooFunc()
而不是 foopkg.FooFunc()
。相反,go 在 2-foofile.go 中看到包名称并将其导入为 foopkg
因为在 go 中包的名称正是 package
之后的名称.go 文件的顶部,前提是它是一个有效的标识符。
该目录的唯一用途是收集一组共享相同包名的文件。 the spec 中重申了这一点
A set of files sharing the same PackageName form the implementation of a package. An implementation may require that all source files for a package inhabit the same directory.
在 go 中,目录与包名称匹配是惯例,但不一定是这种情况,而且通常不是第 3 方包。 stdlib 确实很好地遵守了这一约定。
现在目录确实发挥作用的地方是导入路径。您可以在单个二进制文件中包含 2 个名为“foo”的包,只要它们具有不同导入路径即可,即
/some/path/1/foo
和 /some/path/2/foo
我们可以变得非常时髦,将导入别名化为我们想要的任何东西,例如我可以做
import (
bar "/some/path/1/foo"
baz "/some/path/2/foo"
)
同样,这之所以有效,不是因为包名称必须是唯一的,而是包导入路径必须是唯一的。
从这个陈述中可以学到的另一点见解是——在一个目录中,你不能有两个包名。 go 编译器将抛出一个错误,指出它无法加载包
并且它找到包 foo (foo.go) 和 bar (bar.go)
。
关于go - package语句与.go文件目录的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43579838/