不废话了,从例子中更好总结
eg1: 执行与return位置自底向上
大多数教材说defer方法是先进后出的栈结构, 但我认为从return位置向上找defer更直观
package main
import(
"fmt"
)
func main(){
example()
}
func example() {
defer func(){
fmt.Println("1")
}()
defer func(){
fmt.Println("2")
}()
defer func(){
fmt.Println("3")
}()
return
}
3
2
1
eg2: 进一步说明eg1
package main
import(
"fmt"
)
func main(){
example()
}
func example() {
defer func(){
fmt.Println("1")
}()
defer func(){
fmt.Println("2")
}()
defer func(){
fmt.Println("3")
}()
fmt.Println("4")
fmt.Println("5")
return
}
4
5
3
2
1
eg3: return之下将被忽略
依旧是return位置向上找有没有defer,因此return之下不被执行
package main
import(
"fmt"
)
func main(){
example()
}
func example() {
defer func(){
fmt.Println("1")
}()
defer func(){
fmt.Println("2")
}()
return
defer func(){
fmt.Println("3")
}()
}
2
1
eg4: defer中修改返回值的方法
使用命名返回值(Named Return Value)
package main
import(
"fmt"
)
func main(){
res := ValRetrun()
fmt.Println(res)
}
func ValRetrun()(res string) {
res = "origin"
defer func(){
res = "changed"
}()
return res
}
changed
非命名返回值 defer中的修改无效
package main
import(
"fmt"
)
func main(){
res := ValRetrun()
fmt.Println(res)
}
func ValRetrun()(string) {
res := "origin"
defer func(){
res = "changed"
}()
return res
}
changed
eg5:defer func()参数在defer位置已确定
package main
import(
"fmt"
)
func main(){
example()
}
func example() {
res := "before"
defer func(res string){
fmt.Println(res)
}(res)
res = "after"
defer func(res string){
fmt.Println(res)
}(res)
}
before
又或者
package main
import(
"fmt"
)
func main(){
example()
}
func example() {
res := "before"
defer func(res string){
fmt.Println(res)
}(res)
res = "after"
defer func(res string){
fmt.Println(res)
}(res)
}
after
before
总结:
看完这个例子已经明显,defer除了执行顺序以外,与其他代码块内容上没有太大区别,可以理解为有一个栈,把顺序自上向下的代码中的defer块放进栈中,直到碰到return(或者函数执行完毕,隐式return),再把一个个defer从栈中取出来一个个执行.这样就很好理解defer的执行内容和执行顺序了.