在Go语言中,包名必须和最里面的目录名相同吗?

eqqqjvef  于 2023-03-06  发布在  Go
关注(0)|答案(4)|浏览(439)

注意这个问题是关于Go语言规范的,而不是最佳实践或建议。

我读过很多关于软件包的文章,但是我仍然不太理解目录和软件包名的关系。下面是我的例子。
我的项目结构就像下面的截图。当我执行go run ~/go/src/myproj/main.go时,错误显示:
源代码\我的项目\主文件。转到:5:2:无法在以下任何位置找到软件包“paybaybay.com”:c:\go\源代码\我的项目\pa\pb(来自$GOROOT)C:\用户\terry\go\源代码\我的项目\pa\pb(来自$GOPATH)

但是如果我在p.go中把package pb改成package pa,把import从"myproj/pa/pb"改成"myproj/pa",把main.go中的fmt.Print(pb.Greet)改成fmt.Print(pa.Greet),就可以了,最里面的目录必须和包声明名匹配吗?我的go版本是1.14.4

rekjcdws

rekjcdws1#

在go中,一个约定是包的名字应该等于它的源目录的名字。
下面是Effective Go Blog的一个示例摘录:
另一个约定是包名是其源目录的基名;src/encoding/base64中的包被导入为"encoding/base64",但名称为base64,而不是encoding_base64和encodingBase64。
这样做的效果是一个目录中只包含一个包,这在go中是非常基本的,你可以把它看作是一个固定的规则,尽管从技术上讲,它只是一个约定。

4ioopgfo

4ioopgfo2#

在Go语言中,包名必须和最里面的目录名相同吗?
它不一定要完全相同,但这是一个共同的惯例。除非你有充分的理由,否则你不应该偏离它。
如果你想要一个不同的包名和目录名,你可以在文件的package子句中使用import注解。

package <package_name> // import "<import_path>"

这在文件结构不利于描述性名称时很有用,例如在文件路径中使用多个版本时。
例如,Google的客户端SDK使用如下路径:

  • Package 名称:slides
  • 导入路径:google.golang.org/api/slides/v1

为了支持这一点,文件的package子句如下所示:

package slides // import "google.golang.org/api/slides/v1"

通过这种方式,可以在调用代码中完成以下操作,这看起来很明智。

package main

import(
    "google.golang.org/api/slides/v1"
)

func main() {
    fmt.Println(slides.PresentationsScope)
}

查看更多信息:https://github.com/googleapis/google-api-go-client/blob/master/slides/v1/slides-gen.go
在下面的示例中,您将使用:

package pb // import "myproj/pa"

如果您不使用package子句方法,编辑器可能会自动为您的代码添加别名,例如:

import pb "myprog/pa"
voj3qocg

voj3qocg3#

包名不一定是包目录的基目录。go工具goimports在清理源文件的导入时,如果包名与基目录不匹配,实际上会将包名显示为导入的别名-a为了使导入代码看起来更有意义,但别名不是必需的--文件将在没有别名的情况下编译。当查看包的AST时,types.Package有一个返回包名的Name方法。当用www.example.com函数加载包时golang.org/x/tools/go/packages.Load,返回的 *packages.Package有一个同样返回包名的Name属性。这在按程序生成代码时非常有用。

gtlvzcf8

gtlvzcf84#

经过一些试验和错误,我发现发生了什么。包名必须与最内层的目录名相同吗?不。
main.go中,只需执行以下操作就可以了。

package main

import (
    "fmt"
    "myproj/pa"
)

func main() {
    fmt.Print(pb.Greet)
}

我们也可以给予它一个别名,如下面的工作也.

package main

import (
    "fmt"
    pc "myproj/pa"
)

func main() {
    fmt.Print(pc.Greet)
}

也就是说,go中的package是一个声明了package xxx的文件目录,目录名在导入过程中很重要,目录是导入路径的一部分,但是导入文件中使用的是package xxx中的xxx或者是xxx的别名。
当然,做这样的事情是不建议的,但最好的做法是不要这样做来迷惑人。

相关问题