• Go 为什么不支持从 main 包中导入函数?
  • 发布于 1个月前
  • 57 热度
    0 评论
  • 冰魄
  • 0 粉丝 38 篇博客
  •   
作为一个维护过许多有一定历史沉淀的 Go 项目的人,在历史债务下和奇葩需求下,会遇到一些迫于业务需求的技术诉求。诉求上是希望引用多项目,会出现从 main 包(package)中导入相关函数的这种使用诉求。为了将多 Go 工程合并到一个大单体中使用。

问题案例
具体的使用案例如下。
我们有一个 Go 应用,目录结构如下:
demo1
├── go.mod
├── main.go
└── x
    └── main.go
demo1/x/main.go 文件内代码如下:
package main

import (
 "fmt"
)

func main() {
 Main()
}

func Main() {
 fmt.Println("堆代码 www.duidaima.com")
}
demo1/main.go 文件内代码如下:
package main

import (
 "fmt"

 xmain "example.com/greet/x"  // 也就是本应用,上面的 x
)

func main() {
 fmt.Println("堆代码 duidaima.com")
 xmain.Main()
}
简单来讲,就是 demo1 这个 Go 项目,拥有两个 main 包。根目录下的 main.go 文件内引用了 x/main.go 内的 Main 方法。

运行该程序,看看运行结果:
$ go run main.go
main.go:6:2: import "example.com/greet/x" is a program, not an importable package
会直接报错,提示 x 包下是一个程序,而不是一个可导入的包。

为什么不支持导入 main 包
这个问题稍微可以收敛一下,关键内容是:为什么不支持导入 main 包内的函数?明明 main 包也是一个 package,其个别函数也是大写开头,是允许对外导出的。我首先翻阅了一下 Go 语言规范(spec),确实没有非常明确禁止该项行为。但又确实在我们日常使用和编译运行时,会被拒绝运行。提示前面的错误。

随后又查看了具体的代码提交和 CL,实际上在 13 年前。现任 Go 核心团度负责人 @rsc 是提交过相应 main 包支持的。
如下 CL 所示: