go语言的defer机制可以避免其他语言时处理错误,要在每个分支执行关闭、回收资源的繁杂问题。
百闻不如一见,看的教程再多,也不如自己实际编程,调试来得方便。
以下为根据测试代码段进行总结的过程。
1.
package main
import "fmt"
func test1() {
fmt.Println("循环开始")
var p *int
for i := 0; i < 5; i++ {
fmt.Println("i = ", i)
defer func(i int) {
fmt.Println("this is first defer ", i)
}(i) //带参数
defer func() {
fmt.Println("this is second defer", i*10)
}() //不带参数
p = &i
}
//return //在此处注释
fmt.Println("循环结束")
defer func() {
fmt.Println("this is the last defer")
}()
fmt.Println("修改循环变量i指针之前 i = ", *p)
*p = 1 //在此处注释
fmt.Println("修改循环变量i指针之后 i = ", *p)
}
func main() {
test1()
}
循环开始
i = 0
i = 1
i = 2
i = 3
i = 4
循环结束
修改循环变量i指针之前 i = 5
修改循环变量i指针之后 i = 1
this is the last defer
this is second defer 10
this is first defer 4
this is second defer 10
this is first defer 3
this is second defer 10
this is first defer 2
this is second defer 10
this is first defer 1
this is second defer 10
this is first defer 0
解释:test1()函数有两处代码注释,将其注释或者打开,可以得出以下结论。
1.defer要执行的函数或者语句,与defer语句出现的先后顺序有关系。假设你把每一个defer语句看作 stack.push(),就很容易理解defer执行的顺序了。显然,如果打开return处的注释,就不会执行return后面的defer了。
2.defer函数和普通函数一样,可以带参数,需考虑参数是值还是指针。这一点观看循环里面的输出就很好理解了。不带参数,就有对循环变量i的引用。
func test2() {
f, _ := os.Open(`C:\Users\yyjeqhc\Desktop\bc\1.cpp`)
defer func() {
if err := f.Close(); err != nil {
fmt.Println("1.cpp已经关闭")
} else {
fmt.Println("1.cpp在这里关闭")
}
}()
var fa = func(f *os.File) {
if err := f.Close(); err != nil {
fmt.Println("文件已经关闭")
} else {
name := f.Name()
filename := path.Base(name)
//fmt.Println("不包含目录的文件名:", filename)
fmt.Println("关闭了", filename)
}
}
defer fa(f)
f1, _ := os.Open(`C:\Users\yyjeqhc\Desktop\bc\1.py`)
defer func() {
if err := f1.Close(); err != nil {
fmt.Println("1.py已经关闭")
} else {
fmt.Println("1.py在这里关闭")
}
}()
defer fa(f1)
var t = func(i int) {
fmt.Println("this is a func and i = ", i)
defer func() {
fmt.Println("this is defer in a func", i)
}()
}
t(1)
fmt.Println("-----------------")
t(2)
fmt.Println("this is end")
}
可见输出
this is a func and i = 1
this is defer in a func 1
-----------------
this is a func and i = 2
this is defer in a func 2
this is end
关闭了 C:\Users\yyjeqhc\Desktop\bc\1.py
1.py已经关闭
关闭了 C:\Users\yyjeqhc\Desktop\bc\1.cpp
1.cpp已经关闭