GO学习系列:defer的使用

来源:互联网 发布:如何当网络写手 编辑:程序博客网 时间:2024/06/08 04:53

在学习go的过程中,发现defer的用法,可以延迟返回,

即在函数return前会按照逆序依次调用defer func()。

主要使用在函数返回前需要释放资源时,而函数又有多个return的分支,

为了防止忘记释放资源而导致内存泄漏等,使用defer 统一释放。

例如:

func  A() {

// 申请一些资源

defer funcRelease() //为了防止忘记释放资源,使用defer,return前调用

if stateA {

return

}

if stateB {

return

}

return

}

defer 还有一些需要注意的地方,尽管在代码中可能不会遇到,但还是要注意:

1、defer的顺序

在函数中有多个defer时,defer的执行顺序为先进后出。

例如:

func A() {

i := 1

defer fmt.Println("First Use defer")

defer fmt.Println("Second Use defer")

}

执行结果为

Second Use defer

First Use defer

2、当defer 函数的入参为实时参数时,参数被实时解析

即传入的参数为固定值。

例如

func A() {

i := 1

defer fmt.Println(i + 1)

i++

fmt.Println(i)

return

}

函数的执行顺序为:

i = 1

i ++ 此时i为2

fmt.Println(i)  打印为2,经过i++

defer fmt.Print(i+1) // defer在return前执行,但是在之前已经将参数值传入函数,

传入的i值为1,打印为2

return

3、defer 中有名返回值(而非匿名返回值)

此时,函数return result并非为原子操作,可以分解为三步:

r = result  // 赋值result给堆栈/寄存器

defer func() //执行defer操作

return  //执行return,返回原函数调用位置

例如1:

func A() (result int) {

defer func() {

result = result + 1

}()

return 1

}

此函数返回值result为多少?

执行为:

result = 1(赋值为1)

defer func {result = result +1 } //执行defer,result 为2

return  // 此时result为2

例如 2:使用匿名返回值时

func A() ( int) {

i := 1

defer func() {

i = i + 1

}()

return i

}

此时返回值为多少?

执行顺序为

i = 1 函数内临时变量

result = i (return分解第一步,赋值为1)

defer func() { i = i + 1 } (分解第二步,defer,i为2)

return (分解第三步,返回)

返回值为1

例如3:

func A() (r int) {

t := 5

defer func() {

t = t + 1

}()

return t

}

执行顺序为:

t = 5 // 函数中临时变量t为5

r = t // 分解第一部,赋值,返回值r = 5

defer func() { t = t + 1 } // 分解第二步,t=5,但是r不变

return //分解第三步,返回

返回值为5

例如4:

func A() (r int) {

t := 5

defer func(r int) {

r = r + 5

}(t)

return t

}

执行顺序为:

t = 5 // 函数中临时变量t为5

r = t // 分解第一部,赋值,返回值r = 5

defer func(r int) { 

r = r + 1  // 分解第二步,注意,defer中r为参数值传递,

// 此时,在defer func中的r为一个临时便利r',并非为原来的r 

}(t) 

return //分解第三步,返回

返回值为5


在使用过程中需要注意!!


原创粉丝点击