go-defer

官方文档中对 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
}

参考:

go-internals:defer 关键字

ps: 传值还是传地址对于服务器程序的运行效率是影响很大的 read Go 的代码调优一例

一句话总结:
defer funtion 是在 返回值被赋值后 而 在 surrounding function 退出 丢出返回值 之前执行的,defer function 中可以对返回值进行赋值

2015-03-06