gotips 002: 多阶段 defer

通过简单的'defer'关键字,你可以借助一个小技巧实现在另一个函数的开头和结尾处执行一个函数。下面的图片展示了这一实现方式。


补充信息

在上一个 tip 中的补充材料中,我已经介绍了这种方法的使用。这里我再举一个例子。

在 Java 等编程·语言生态圈中,有一些单元测试的框架如 JUint, 可以为单元测试开始前设置一些初始环境 (Setup 方法),单元测试结束时执行一些清理动作 (Teardown 方法),在 Go 语言中该怎么实现呢?

我们就可以使用 tip #002 这种方式实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import "testing"
func setupTestCase(t *testing.T, msg string) func(t *testing.T) {
t.Log(msg + ": setup test case")
return func(t *testing.T) {
t.Log(msg + ": teardown test case")
}
}
func TestSetupTestCase(t *testing.T) {
defer setupTestCase(t, "TestSetupTestCase")(t)
t.Log("Run test")
}

你可以专门为你的某个单元测试写一个 setupTestCase, 执行特定的初始化和清理逻辑,也可以为一批单元测试函数写一个通用的初始化和清理逻辑。

说起清理,官方 testing 库中有 t.Cleanupb.Cleanuptb.Cleanupf.Cleanup 方法,可以注册多个清理函数,执行完测试或者子测试后就会被调用,后进先出。