defer是个Go语言中的一个关键词。从语法上来讲,defer语句是defer关键词后面跟着一个函数/方法调用。函数和参数表达式在defer语句所在的位置就已经被检验了。但是实际上的函数/方法调用的话,一直推迟到所在函数的返回结束或者出错结束。任何调用都可以被推迟。多个被推迟的函数调用,实际调用顺序正好与它们代码调用位置相反。
func print(a int) {
fmt.Println(a)
}
func Add(a, b int) int {
defer print(a)
a = a + b
return a
}
fmt.Println(Add(4, 3))
上面这段代码,defer语句输出的是4,Add返回的值是7。
defer可以用于文件的打开和关闭,锁的打开和关闭。
package ioutil
func ReadFile(filename string) ([]byte, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.close()
return ReadAll()
}
上面的代码在执行完return语句后,文件指针f被关闭。
var mu sync.Mutex
var m = make(map[string]int)
func lookup(key string) int {
mu.Lock()
defer mu.Unlock()
return m[key]
}
上面代码先上锁,进入临界区,返回m里key对应的值,然后退出临界区,解除锁。
如果函数的返回值有变量名,defer可以用于打印函数返回值。这在debug中有一定用处。
func double(x int) (result int) {
defer func() { fmt.Println("double(%d) = %d\n", x, result) }()
return x + x
}
_ = double(4)
上面的函数会输出“double(4) = 8"。