Go-延时函数defer

关于延时调用函数(Deferred Function Calls)

     延时调用函数基本语法如下:

defer func_name(param-list) {}

  当一个函数前有关键字 defer 时,那么这个函数执行会被推迟到包含这个 defer 语句的函数即将返回前才执行,

如下示例:

package main

import "fmt"

func main() {
	defer fmt.Println("Fourth")
	fmt.Println("First")
	fmt.Println("Third")
}

  运行打印输出结果:

First
Third
Fourth

 需要注意的是,defer 调用的函数参数,在定义 defer 时就已经被确定了,如下示例:

package main

import "fmt"

func main() {
	i := 1
	defer fmt.Println("Deferred print:",i)

	i++
	fmt.Println("Normal print:",i)
}

  运行打印输出结果:

Normal print: 2
Deferred print: 1

  从上面的结果中我们可以知道,在 defer fmt.Println("Deferred print:"i,) 调用时,i 的值就已经被确定了,因此相当

于 defer fmt.Println("Deferred print:",1)

    需要强调的是,defer 调用的函数的参数值在 defer 定义时就已经被确定了,而 defer 函数内部所使用的变量的值需

要在运行时才确定。如下示例:

package main

import "fmt"

func f1() (r1 int) {
	r := 1
	defer func() {
		r ++
		fmt.Println(r)
	}()

	r = 2
	return
}

func main() {
	f1()
}

  运行打印输出结果:

3

  上面的例子中,我们看到最终打印的内容是 "3" ,这是因为在 "r = 2" 之后才执行的 defer 函数,因此在这个函数内,

r 的值是 2,自增后变成 3

defer 顺序

       如果有多个 defer 调用,则调用的顺序是先进后出的顺序,类似于入栈出栈操作一样:

package main

import "fmt"

func main() {
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	defer fmt.Println(4)
}

  运行打印输出结果:

4
3
2
1

defer 注意要点

       defer 函数调用的执行时机是外层函数设置返回值之后,即将返回之前

       如下示例:

package main

import "fmt"

func f1() (r int) {
	defer func() {
		r ++
	}()

	return 0
}

func main() {
	fmt.Println(f1())
}

  运行打印输出结果:

1

  上面 fmt.Println(f1()) 打印的结果是 1,要弄明白这个问题,我们需要牢记两点:

       1. defer 函数调用的执行时机是外层函数设置返回值之后,即将返回之前

       2.return xxx 操作并不是原子

       我们将上面的例子改写一下:

func f1() (r int) {
	defer func() {
		r ++
	}()

	r = 0
	return
}

  当进行赋值操作 r = 0 之后,才执行调用 defer 函数,最后才执行返回语句

       下面我们再看一个例子:

package main

import "fmt"

func double(x int) int  {
	return x + x
}

func triple(x int) (r int)  {
	defer func() {
		r += x
	}()

	return double(x)
}

func main() {
	fmt.Println(triple(3))
}

  上面的代码根据我们的讲解,可以改写成如下代码:

func triple(x int) (r int)  {
	r = double(x)
	defer func() {
		r += x
	}()
	
	return
}

  匿名返回值:

package main

import "fmt"

func a() int  {
	var i int

	defer func() {
		i ++
		fmt.Println(i)
	}()

	defer func() {
		i ++
		fmt.Println(i)
	}()

	return i
}

func main() {
	fmt.Println("a return: ",a())
}

   运行打印输出结果:

1
2
a return:  0

  

上一篇:Go-常见的面试题(一)


下一篇:go语言异常处理