突然刷到一些go的关键字用法,自己完全不了解,在这个笔记里面做一个简单总结。
defer
- defer关键字用于注册延迟调用;
- 这些调用直到包含当前该defer关键字的函数执行完了才会被执行;
- 如果定义了多个defer语句,按照先进后出的方式执行,也即后定义的defer语句会先被执行,这也比较好理解,如果之前的资源释放掉了,后面需要使用掉之前资源的语句就没法执行了(可以用来逆序输出内容);
import (
"fmt"
)
func f1() {
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
}
func main() {
f1()
}
就比如上面这个输出就是:321,可以用于逆序输出是很值得记录的一个点。
但这个是多defer关键字注册延迟的情况,如果是:
package main
import "fmt"
type S struct{}
func (s S) p(n int) S {
fmt.Print(n)
return s
}
func main() {
var s S
defer s.p(1).p(2).p(3)
//fmt.Print(4)
}
那么这种方法链将让逆序输出无效,它的输出是:123
并且这种方法链其实只defer了最后一个方法即,s3.p(3)的执行,如果我们让main函数里面的打印恢复正常,那么会打印出来:1243,也就是说只有s3.p(3)会在main函数执行后执行。
func main() {
var s S
defer s.p(1).p(2).p(3)
fmt.Print(4)
}
4. defer语句中的变量,在defer声明的时候就决定了,也即在defer语句中使用到的变量的值为在defer语句之前的变量值(不包括匿名函数)
这里就不得不提“闭包”的使用带来的影响,因为defer语句中的值是根据该语句之前的变量最终值决定,所以如果放在一个循环里面,要打印出来循环对应的参量,那么循环defer只会打出来一个不变的最后的变量。
package main
import "fmt"
func f1() {
a := []int{1, 4, 6, 2, 7}
for _, v := range a {
defer func() {
fmt.Println(v)
}()
}
}
func main() {
f1()
}
defer语句主要有三个方面的用途:
- 关闭文件句柄;
- 锁资源释放;
- 数据库连接释放。