
go 不会自动包含同目录下所有 `.go` 文件;使用 `go run` 时必须显式列出所有源文件(如 `go run main.go otherfile.go`)或使用通配符(如 `go run *.go`),否则函数、变量等跨文件定义将无法解析。
在 Go 中,同一目录下的所有 .go 文件确实属于同一个包(例如 package main),也共享同一作用域——但这仅在它们被同时参与编译时才成立。关键点在于:Go 的构建工具链(尤其是 go run)默认只编译你明确指定的文件,不会自动递归或隐式包含同目录下的其他 .go 文件。
因此,当你执行:
go run main.go
Go 编译器仅加载并编译 main.go 这一个文件。此时 foo() 在该文件中未定义,自然报错 undefined: foo,即使 otherfile.go 也在同一目录且同属 main 包。
✅ 正确做法是显式提供所有需参与编译的源文件:
go run main.go otherfile.go
或者(在 Bash/Zsh 等支持通配符的 shell 中):
go run *.go
? 提示:*.go 会被 shell 展开为当前目录下所有 .go 文件(按字母序),等价于手动列出全部文件。Windows CMD 不支持此语法,需改用 go run main.go otherfile.go;PowerShell 可用 go run (Get-ChildItem *.go).FullName,但推荐统一使用显式列表以保证可移植性。
此外,还需确保以下几点:
- 所有文件 package 声明一致(如均为 package main);
- 函数/变量首字母大写(如 Foo())仅影响导出可见性,与跨文件调用无关(foo() 小写也可在同包内直接调用);
- 无循环导入(本例不涉及 import 循环,因未跨包)。
? 总结:Go 的“单包即单作用域”前提,是所有 .go 文件共同构成一次完整的编译单元。go run 的参数决定了这个单元的边界——它不是基于目录,而是基于你传入的文件列表。养成习惯:开发阶段用 go run *.go 快速验证,生产构建则推荐使用 go build 或模块化项目结构(含 go.mod),由 go build 自动识别整个包。










