go 1.4 引入 `testmain` 函数,允许在所有测试执行前后统一进行初始化和清理操作;但需确保 go 版本 ≥1.4,且必须显式调用 `m.run()` 并通过 `os.exit()` 退出,否则测试框架无法正确接管流程。
在 Go 测试中,若希望在每个测试函数执行后自动清理资源(如重置数据库、关闭连接、清空缓存等),需明确区分两种场景:
⚠️ 重要前提:testing.M 类型自 Go 1.4 起引入。若遇到 undefined: testing.M 错误,请先运行 go version 确认版本。低于 1.4 的环境不支持该特性。

TestMain 不会“在每个测试后运行”,而是在所有测试开始前执行初始化,在 m.Run() 返回后执行收尾。示例:
package main
import (
"os"
"testing"
)
// 模拟测试前准备(如创建临时目录、启动 mock server)
func setup() {
// e.g., os.MkdirAll("testdata", 0755)
}
// 模拟测试后清理(如删除临时文件、关闭服务)
func teardown() {
// e.g., os.RemoveAll("testdata")
}
func TestSomeTest(t *testing.T) {
t.Cleanup(func() {
// ✅ 推荐:每个测试专属的后置清理(Go 1.14+)
// 例如:重置数据库记录、恢复全局状态
t.Log("cleaned up after TestSomeTest")
})
t.Log("running TestSomeTest")
}
func TestMain(m *testing.M) {
setup()
// 必须调用 m.Run() 启动测试流程
code := m.Run()
teardown()
// 必须用 os.Exit(code),否则 defer 不生效且测试可能提前退出
os.Exit(code)
}| 目标 | 推荐方式 |
|---|---|
| 每个测试函数结束后清理(如重置状态) | t.Cleanup(func())(Go 1.14+)或 defer |
| 整个测试包启动前/关闭后执行(如 DB schema 迁移) | func TestMain(m *testing.M)(Go 1.4+) |
| 兼容旧版 Go( | 使用 init() + 全局变量 + 手动管理生命周期(不推荐,易出错) |
升级 Go 版本并合理组合 TestMain 与 t.Cleanup,可构建健壮、高效、可维护的测试套件。