
Go 工具链在构建非测试环境时会自动排除所有以 _test.go 结尾的文件,因此测试文件中定义的变量(即使同包)对 go build 或 go run 不可见,导致“undefined”编译错误。
go 工具链在构建非测试环境时会自动排除所有以 `_test.go` 结尾的文件,因此测试文件中定义的变量(即使同包)对 `go build` 或 `go run` 不可见,导致“undefined”编译错误。
这是 Go 构建模型的核心设计原则:测试文件仅用于测试上下文,不参与常规包构建。当你执行 go test ./db 时,Go 会编译 add.go 和 add_test.go 并链接为测试二进制;但执行 go run main.go 或 go build ./db 时,add_test.go 被完全忽略——这意味着其中声明的变量 a、b 对 add.go 来说根本不存在,自然触发 undefined: a 编译错误。
✅ 正确做法是:将需共享的变量/逻辑提取至普通源文件中。例如:
// db/vars.go
package db
// Exported or unexported as needed — visible to all non-test files in the package
var (
A = 1 // exported if external access needed
b = 2 // unexported, internal use only
)
然后在 add.go 中直接使用:
// db/add.go
package db
func Add(x, y int) int {
return x + y
}
// 示例:使用共享变量 b(注意:b 是 unexported,仅本包可用)
func AddWithDefault(x int) int {
return Add(x, b) // ✅ now valid
}
同时更新测试文件,保持一致性:
// db/add_test.go
package db
import "testing"
func TestAddWithDefault(t *testing.T) {
result := AddWithDefault(A) // ✅ uses exported A and internal b
if result != 3 {
t.Errorf("expected 3, got %d", result)
}
}
⚠️ 注意事项:
- 不要依赖 _test.go 文件提供运行时逻辑——它本质是隔离的测试沙盒;
- 若变量仅用于测试,可保留在 _test.go 中,但主逻辑必须通过参数或接口注入,而非直接引用;
- go list -f '{{.TestGoFiles}}' ./db 可查看哪些文件被识别为测试文件;
- 使用 go build -v ./db 可验证构建时实际参与编译的源文件列表(不含 _test.go)。
总结:Go 的包构建严格区分「生产代码」与「测试代码」。跨文件共享数据必须置于常规 .go 文件中,这是保障构建确定性与模块清晰性的关键约定。











