golang中defer的使用以及注意事项
为什么需要defer
在函数中,程序猿经常需要创建资源(数据库连接、文件句柄、锁等),为了函数在执行完毕后,及时释放资源,Go的设计者提供了defer(延时释放资源)。
入门案例
func sum(n1 int, n2 int) int { //当执行到defer时,暂时不执行,会将defer后面的语句压入到独立的栈(defer栈) //当函数执行完毕后,再从defer栈中按照先入后出的方式执行 defer fmt.Printf("ok1 n1: %v\n", n1) defer fmt.Printf("ok2 n2: %v\n", n2) res := n1 + n2 fmt.Printf("ok3 res: %v\n", res) return res } func main() { res := sum(10, 20) fmt.Printf("res: %v\n", res) }
运行结果
ok3 res: 30 ok2 n2: 20 ok1 n1: 10 res: 30
注意事项
-
当go执行到一个defer时,不会立即执行defer后的语句,而是将defer后的语句压入到一个栈中,然后执行下一条语句。
-
当函数执行完毕时,在从defer栈中,依次从栈顶取出语句执行
-
在defer将语句放入到栈时,也会将相关的值拷贝同时入栈。
如:
func sum(n1 int, n2 int) int { defer fmt.Printf("ok1 n1: %v\n", n1) defer fmt.Printf("ok2 n2: %v\n", n2) n1++ //此时再更改n1,n2的值,不会影响上面语句中的n1,n2 n2++ res := n1 + n2 fmt.Printf("ok3 res: %v\n", res) return res } func main() { res := sum(10, 20) fmt.Printf("res: %v\n", res) }
运行结果
ok3 res: 32 ok2 n2: 20 ok1 n1: 10 res: 32