go - package语句与.go文件目录的关系

标签 go import package

查看此实验。

~/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)

参见 https://golang.org/doc/code.html#PackageNames获取更多信息。

关于go - package语句与.go文件目录的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43579838/

相关文章:

unit-testing - 初始化循环 Golang

go - 访问基本身份验证凭据

java - 如何在eclipse中以分层 View 创建包

node.js - 如何从 package.json 运行启动脚本?

arrays - Golang 创建 bytes.Buffer 数组的多读取器

go - 如何编写一个目录遍历程序,可以反馈子目录、文件等的总数?

python - 想要在 Jupyter Notebook (Anaconda) 中保存并运行 Python 脚本

import - 读取固定宽度文件 - 识别空格

arrays - 在 Google Sheet 上将多个列堆叠在一起?

dependencies - NuGet:pack命令不包括nuget依赖项