defer关键字
defer和go一样都是Go语言提供的关键字. defer用于资源的释放, 会在函数返回之前进行调用. 要使用好defer最重要的是要理解return执行过程: 先给返回值赋值, 然后调用defer表达式, 最后才是返回到调用函数中. 理解了这句话, 关于defer的疑惑都能迎刃而解了.
例子
例一:
func f1() (result int) {
defer func() {
result++
}()
return 0
}
return时先将对result赋值0, 然后defer中对result++, 此时result=1; 最后返回时result=1,即调用函数获得值1.
例二:
func f2() (r int) {
t := 5
defer func() {
t = t + 5
}()
return t
}
return时先将t的值5赋值给r(值传递); 然后defer中对加5,此时t=10,r=5; 最后返回时r=5, 即调用函数获得值5.
例三:
func f3() (r int) {
defer func(r int) {
r = r + 5
}(r)
return 1
}
return时先将1赋值给r; 然后调用defer时将r的值传递给defer函数, 注意defer函数中的r已经与函数f3返回的r不是一个变量(值传递), 因此r的修改不会影响f3返回值; 最后返回时r=1, 即调用函数获得值1.
例四:
func addCounter() {
for count := 0; count < 2; count++ {
defer lock.Unlock()
//do someThing
lock.Lock()
}
}
将解锁放到defer中是为了防止执行任务(do someThing)时panic导致程序异常结束而未解锁。实际运行时该例子会产生死锁, 原因是(1) Muxtex不是可重入锁; (2) defer会在函数结束时执行,而不是在每一轮for循环结束时执行。正确写法如下:
func addCounter() {
for count := 0; count < 2; count++ {
doSomeThing()
}
}
func doSomeThing() {
lock.Lock()
defer lock.Unlock()
//do someThing
}