go中main包的怪癖

背景

发现若main包中的内容分布在多个文件中,则运行时需要指定所有文件.

举例

main.go

1
2
3
4
5
package main

func main() {
f1()
}

external.go

1
2
3
4
5
6
7
8
package main

import "fmt"

func f1() {
fmt.Println(123)
}

运行时

1
go run main.go

报错 undefined: f1

而需要

1
2
3
4
5
go run main.go external.go
#
go run .
# 甚至是用module名也可
go run <module-name>

猜测原因

被import的包,能够使用一定方法查找并加载依赖文件.
而main包由于不能被import,因此需要手动指定哪些是依赖文件.
如果不以被import为依据去加载依赖,可能因此会有许多没有用到的文件会被加载,浪费资源.

官方说法

go run 命令可以接许多内容

  • 一个文件
  • 多个文件
  • 文件夹名
  • 包名

且最典型的用法是 go run . 而非 go run main.go

go help run 的输出结果也可以提供一些帮助,
但依然没有指明go到底在什么时机查找依赖的.

大致结论

复杂项目,只在 main.go 里放main包的内容.比如用于启动服务器等.
这样好在运行项目时能够统一命令为 go run main.go

参考

  1. 其他人有同样的现象1
  2. 其他人有同样现象2
  3. 官方佐证