Go测试函数中变量声明与普通函数一致,用var、:=或字面量即可;临时变量作用域限于当前测试,无需手动清理;禁止包级变量复用测试数据以防污染;命名需语义明确;切片/map/指针需注意隐式共享问题。

测试函数里直接声明变量就行,不用特殊语法
Go 的测试函数 TestXxx 就是普通函数,变量声明和日常写法完全一致——用 var、:= 或结构体字面量都行。临时变量生命周期只在当前测试函数内,跑完自动释放,无需手动清理。
常见错误是误以为测试中要“注册”或“注入”变量,比如试图用 t.Cleanup 管理局部变量——其实没必要,那玩意儿只适合关文件、停 goroutine 这类外部资源。
-
name := "test-user"—— 最常用,简洁明确 -
var cfg Config; cfg.Timeout = 5—— 适合需要零值初始化再赋值的场景 -
data := []string{"a", "b"}—— 切片、map、struct 字面量照常使用
避免在多个测试函数间共享变量
别在测试文件顶部用 var 声明包级变量来“复用”测试数据,这会导致测试间污染。比如一个测试改了 globalInput,下一个测试可能读到脏值,尤其并行测试(t.Parallel())时极难排查。
正确做法是每个测试函数内部独立构造所需数据:
立即学习“go语言免费学习笔记(深入)”;
func TestParseJSON(t *testing.T) {
t.Parallel()
input := `{"id": 123}` // 每次都新建
var out struct{ ID int }
if err := json.Unmarshal([]byte(input), &out); err != nil {
t.Fatal(err)
}
}
- 即使内容一样,也重复写
input := ...,不图省事 - 若构造逻辑复杂(如生成带时间戳的 fixture),可封装成私有函数,但函数内部仍应返回新实例,而非复用全局对象
- 包级变量只用于真正不变的常量,比如
const testURL = "http://localhost:8080"
临时变量命名要体现用途,别用 v、x 这类符号
测试代码的可读性比实现代码还重要——别人(或三天后的你)得一眼看懂这个变量在测什么。用模糊名会拖慢调试速度,尤其当断言失败时,日志里只显示 v == 42 根本看不出上下文。
- 输入数据用
inputJSON、rawBody、malformedHeader - 期望结果用
expectedErr、wantCode、wantUser - 中间状态用
parsed、resp、actual(配合want使用)
Go 测试惯例不强制匈牙利命名,但含义必须直白。比如 err 可以,e 就不行;users 可以,u 就不行。
注意指针和切片的隐式共享问题
临时变量如果是切片、map 或结构体指针,赋值时不是深拷贝。如果后续修改它,可能意外影响其他变量——这在构造多组相似测试数据时特别容易踩坑。
base := User{Name: "default", Roles: []string{"user"}}
u1 := base // 复制结构体,但 Roles 切片底层数组共享
u2 := base
u1.Roles = append(u1.Roles, "admin") // u2.Roles 也会变!
- 用
copy或append([]T(nil), src...)显式复制切片 - map 要用
for k, v := range src { dst[k] = v }手动复制 - 更稳妥的是每次用字面量重建:
u1 := User{Name: "a", Roles: []string{"user", "admin"}}
这类共享问题不会报错,但会让测试随机失败,尤其在并行执行时。只要涉及可变复合类型,就默认按需重建,别图省事复用。


















