
Go test 并行执行为什么没变快?
并行测试(go test -p)默认只控制构建并发数,不是运行时测试函数的并发——真正让 TestXxx 并行跑,得在函数里显式调用 t.Parallel()。
常见错误是只加了 -p 4 就以为所有测试都并发了,结果 go test 还是一个接一个跑 TestA、TestB,压根没触发并行逻辑。
-
t.Parallel()必须放在测试函数最开头(甚至早于t.Log或 setup),否则会被忽略 - 同个测试文件里,所有调用了
t.Parallel()的函数会按组调度,并发执行;没调的仍串行,且会阻塞整组启动 - 注意副作用:并行测试共享包级变量或临时目录时容易竞态,
go test -race要常开
如何安全复用测试中的 HTTP server 或数据库连接?
反复启停 http.Server 或重连 DB 是慢的主要原因,但直接全局复用又会导致测试间污染。Go 测试生命周期短,适合用「懒初始化 + 每次测试独占资源」的折中方式。
比如数据库连接池可以全局复用(sql.DB 本身线程安全),但事务、测试数据必须隔离:
立即学习“go语言免费学习笔记(深入)”;
- 用
db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelReadUncommitted})而非直接db.Exec,确保每测回滚 - HTTP server 推荐用
httptest.NewUnstartedServer,每次测试手动.Start()和.Close(),避免端口冲突 - 别在
init()里初始化任何有状态服务——测试运行顺序不保证,go test -run TestA可能跳过初始化逻辑
测试缓存该存什么、不该存什么?
Go 测试里所谓“缓存”,本质是避免重复计算或 IO,但缓存位置和生命周期极易出错。真正的加速点只有两类:纯函数结果、可复现的外部依赖响应。
比如解析固定 JSON Schema、生成固定结构的 mock 数据,可以用 sync.Once + 包级变量缓存;但涉及时间、随机数、环境变量的绝对不能缓存。
- 推荐模式:
var once sync.Once; var cachedResult Result; once.Do(func(){ cachedResult = heavyComputation() }) - 禁止缓存:
time.Now()、rand.Intn()、os.Getenv("ENV")、任何*http.Client发起的真实请求返回值 - 如果用了
testify/mock或gomock,mock 对象本身不要缓存——不同测试可能需要不同行为断言
go test -count=1 与 -count=2 性能差异大?
-count=N 不是“跑 N 次”,而是「复用同一套编译产物,N 次执行测试二进制」。第一次会编译+运行,后续只是重新执行——所以第二次起快,不是因为缓存,是因为跳过了 build 阶段。
但它会复用全部全局状态(包括未清理的 map、未关闭的 goroutine、未 reset 的计时器),导致第二次运行失败或结果异常,尤其在有 init() 或包级变量的测试中。
- 仅适合纯函数类测试(无副作用、无状态、无 goroutine)做快速验证
- 只要测试里有
time.Sleep、http.ListenAndServe、defer close(ch),就别用-count>1 - 想压测性能?用
benchstat+go test -bench,别拿-count当性能工具
最常被忽略的是:测试文件里写了 func init() { log.SetOutput(ioutil.Discard) },-count=2 时日志设置不会重置,第二轮测试可能漏掉关键 debug 输出。










