defer关键字
defer
是Golang中一个非常重要的关键字,主要是用于注册延迟调用,这些调用在return
时才会执行,通常用来销毁资源
示例
简单场景
最简单的使用场景
import "fmt"
type handler struct {
}
func (h *handler) close() {
fmt.Println("close handler")
}
func (h *handler) call() {
fmt.Println("call function exec")
}
func main() {
h := new(handler)
defer h.close()
h.call()
}
call function exec
close handler
defer
注册的函数是在return
返回时才会被调用,主要用于关闭一些资源句柄之类的
多次注册
注册多个调用的场景
package main
import "fmt"
type handler struct {
}
func (h *handler) close1() {
fmt.Println("close1 handler")
}
func (h *handler) close2() {
fmt.Println("close2 handler")
}
func (h *handler) call() {
fmt.Println("call function exec")
}
func main() {
h := new(handler)
defer h.close1()
defer h.close2()
h.call()
}
call function exec
close2 handler
close1 handler
defer
允许注册多个调用,按先进后出的顺序执行
变量修改
在注册后修改了变量所指向的值的情况
package main
import "fmt"
type handler struct {
i int
}
func (h *handler) close() {
fmt.Println(h.i, "close handler")
}
func main() {
h := &handler{i: 1}
defer h.close()
h = &handler{i: 2}
}
1 close handler
defer
所注册的函数参数会被复制一份保存起来,并不受后续的修改所影响
不过要注意的是这里只是复制了go
的指针,指针指向的地址不会变,但是指针指向的地址上的内容是可以修改变动的
闭包
与上面一种场景相似的就是闭包的场景
package main
import "fmt"
type handler struct {
i int
}
func (h *handler) close() {
fmt.Println(h.i, "close handler")
}
func main() {
h := &handler{i: 1}
defer func() {h.close()}()
h = &handler{i: 2}
}
2 close handler
类似于上面的指针,闭包不会发生改变,但是闭包所引用的值h
可以发生改变
异常情况
在调用os.Exit
、log.Fatal
这些函数直接退出程序时,defer
注册的函数不会被执行