2、return XXX 操作并不是原子的.
我们将上面的例子改写一下大家就很明白了:
func f1() (r int) {
defer func() {
r++
}()
r = 0
return
}
当进行赋值操作 "r = 0" 后, 才调用 defer 函数, 最后才是返回语句.
因此上面的代码等效于:
func f1() (r int) {
r = 0
func() {
r++
}()
return
}
接下来我们再来看一个更有意思的例子:
func double(x int) int {
return x + x
}
func triple(x int) (r int) {
defer func() {
r += x
}()
return double(x)
}
func main() {
fmt.Println(triple(3))
}
如果我们已经理解了上面所说的内容的话, 那么 triple 函数就很好理解了, 它实际上是:
func triple(x int) (r int) {
r = double(x)
func() {
r += x
}()
return
}
defer 表达式的使用场景
defer 通常用于 open/close, connect/disconnect, lock/unlock 等这些成对的操作, 来保证在任何情况下资源都被正确释放. 在这个角度来说, defer 操作和 Java 中的 try ... finally 语句块有异曲同工之处.
例如:
var mutex sync.Mutex
var count = 0
func increment() {
mutex.Lock()
defer mutex.Unlock()
count++
}
在increment 函数中, 我们为了避免竞态条件的出现, 而使用了 Mutex 进行加锁. 而在进行并发编程时, 加锁了却忘记(或某种情况下 unlock 没有被执行), 往往会造成灾难性的后果. 为了在任意情况下, 都要保证在加锁操作后, 都进行对应的解锁操作, 我们可以使用 defer 调用解锁操作.
总结
以上就是这篇文章的全部内容,希望对大家的学习或者工作带来一定的帮助。如果有疑问大家可以留言交流。









