官方文档中对 defer 的作用是这样描述的:
Instead, deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred.
其中的给出的例子也很好理解:
lock(l)
defer unlock(l) // unlocking happens before surrounding function returns
// prints 3 2 1 0 before surrounding function returns
// 用中文来讲就是先入后出
for i := 0; i <= 3; i++ {
defer fmt.Print(i)
}
// f returns 1
func f() (result int) { //golang 可以 显式的 对用返回值进行操作
defer func() {
result++
}()
return 0
}
但总会有一些细节没有暴露出来,想想:
func useAssign(){
n := 10
defer func() { // 在这里去掉 defer 或留着 结果是不一样,为什么 ?
n = 111 // 在这里 defer 中的 function 修改的并不是返回值,而是 surrounding function 的一个 local variable
}()
return n
}
func useAssign(){
n := 10
func(tmp *int) {
*tmp = 111 // 在这里 因为返回地址没有显示给出,defer 中的 function 修改的并不是返回值,而是 surrounding function 的一个 local variable
}(&n)
return n
}
func useReturnParameter() (r int) {
r = 100
defer func(tmp int) {
tmp = 199 // 结果并不是 199, 为什么?最基础的传值还是传地址问题,golang 可以 显式的 对用返回值进行操作,但在这里只是对 返回值的 拷贝进行赋值,并不影响最终的返回值的
}(r)
defer func(tmp *int) {
*tmp = 199 // 传地址,会修改返回值
}(&r)
return r
}
func useReturnParameter() (r int) {
r = 100
defer func() { // 而这里不管去掉 defer 与否,结果都是一样的
r = 199 //golang 可以 显式的 对用返回值进行操作
}()
return r
}
参考:
ps: 传值还是传地址对于服务器程序的运行效率是影响很大的 read Go 的代码调优一例
一句话总结:
defer funtion 是在 返回值被赋值后 而 在 surrounding function 退出 丢出返回值 之前执行的,defer function 中可以对返回值进行赋值