Go中包名必须和最里面的目录名一样吗?

问题描述 投票:0回答:4

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

我读了很多关于包的文章,但还是不太明白目录和包名的关系。这是我的例子。

我的项目结构如下图所示。当我这样做时

go run ~/go/src/myproj/main.go
错误提示:

src\myproj\main.go:5:2:在以下任一位置找不到包“myproj/pa/pb”: c:\go\src\myproj\pa\pb (来自 $GOROOT) C:\Users erry\go\src\myproj\pa\pb (来自 $GOPATH)

enter image description here

enter image description here

但是,如果我在 p.go 中将

package pb
更改为
package pa
,并将导入从
"myproj/pa/pb"
更改为
"myproj/pa"
,并将 main.go 中的
fmt.Print(pb.Greet)
更改为
fmt.Print(pa.Greet)
,它将起作用。最里面的目录必须与包声明名称匹配吗?我的go版本是1.14.4

go package go-modules package-name
4个回答
9
投票

经过一番尝试和错误后,我发现发生了什么事。 包名称必须与最内层目录名称相同吗?没有。

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 的别名。

当然,不建议这样做,但最好的做法还是不要这样做来迷惑人们。


7
投票

在 Go 中,包名必须与最内层目录名相同吗?

不一定要完全相同,但这是一个通用约定。除非你有充分的理由,否则你不应该偏离它。

如果你想有不同的包名和目录名,你可以使用 import 注释和 files 的 package 子句。

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

这对于您的文件结构不利于描述性名称很有用,例如,如果在文件路径中使用多个版本。

例如,Google 的客户端 SDK 使用如下路径:

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

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

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"

7
投票

在 Go 中,一个约定是包的名称应该等于其源目录的名称。

这里是 Effective Go 博客的摘录:

另一个约定是包名称是其源目录的基本名称; src/encoding/base64 中的包被导入为“encoding/base64”,但名称为

base64
,而不是encoding_base64,也不是encodingBase64。

这会导致单个目录仅包含一个包。它在 Go 中是如此基础,以至于你可以将其视为一个固定规则,尽管从技术上来说,它只是一个约定。


1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.