Go 语言 defer(延迟) 关键字基本用法详解
Defer 语句用于在使用defer关键字的函数返回之前执行函数调用。
上面这个说法可能看起来比较复杂,但通过一个例子来理解就会感觉很简单。
package main
import (
"fmt"
)
func finished() {
fmt.Println("Finished finding largest")
}
func largest(nums []int) {
defer finished()
fmt.Println("Started finding largest")
max := nums[0]
for _, v := range nums {
if v > max {
max = v
}
}
fmt.Println("Largest number in", nums, "is", max)
}
func main() {
nums := []int{78, 109, 2, 563, 300}
largest(nums)
}
上面是一个简单的程序,用于查找给定的整数切片的最大值。 函数 largest()
将一个 int 切片作为参数并打印该切片的最大数字。 largest() 函数的第一行包含语句 defer finished()
。 这意味着 finished() 函数将在 largest() 函数返回之前被调用。 运行这个程序,我们可以看到下面的输出。
largest() 函数开始执行并打印上述输出结果的前两行。 在它可以返回之前,我们的 defer 函数完成执行并打印文本“Finished finding largest”:)
从上面的示例中我们可以看到,defer 语句不管是在函数中的什么位置,都会在该函数中其他代码执行完之后,函数返回之前才执行。defer finished()
语句是在 largest() 函数中的最开始的位置,但是我们发现它是在最后执行的。

延迟方法
Defer 不仅限于函数。也可以在方法前面使用。我们来看一下下面这段代码
package main
import (
"fmt"
)
type person struct {
firstName string
lastName string
}
func (p person) fullName() {
fmt.Printf("%s %s",p.firstName,p.lastName)
}
func main() {
p := person {
firstName: "John",
lastName: "Smith",
}
defer p.fullName()
fmt.Printf("Welcome ")
}
在上面的代码中,我们在结构体 person 的方法 fullName() 前使用了defer关键字—— defer p.fullName()
。
上面程序运行结果如下
参数评估
defer 函数的参数在执行 defer 语句时计算,而不是在实际函数调用完成时计算。
要怎么理解这句话呢? 老样子,我们还是先通过一段代码来理解
package main
import (
"fmt"
)
func printA(a int) {
fmt.Println("value of a in deferred function", a)
}
func main() {
a := 5
defer printA(a)
a = 10
fmt.Println("value of a before deferred function call", a)
}
上面的代码输出结果如下
通过上面的代码我们看到 defer printA(a)
在执行的时候参数 a 的值就已经确定了,而不是等到函数printA()执行的时候才去确定当前a的值。
我们通过之前的介绍知道 defer 语句不管是放在函数内部的什么位置,由defer修饰的函数或者方法都是在包含它的函数中的其他语句执行完成之后,在函数返回之前才会去调用。然而,虽说是最后调用,但是它的参数是早在内核执行 defer printA(a)时就已经确定了,将当时传参的值保存到函数栈中了。到后面要调用的时候直接获取的是已经保存到栈中的值。
也就是说
func main() {
a := 5
defer printA(a)
a = 10
fmt.Println("value of a before deferred function call", a)
}
上面这段代码和下面这段代码结果是不同的
func main() {
a := 5
a = 10
defer printA(a)
fmt.Println("value of a before deferred function call", a)
}
虽说 printA(a) 被调用的位置是相同的。
到这我们应该可以理解,虽然在执行 defer 语句后 a 的值变为 10,但实际的调用延迟函数 printA(a) 时仍然打印 5。
本篇我们对Go defer的基本用法进行了介绍,在下一篇 深入理解 defer关键字及defer实践 中对其进入详细介绍。
相关文章
在 JavaScript 中验证 Google ReCaptcha 第 2 版
发布时间:2024/03/23 浏览次数:193 分类:JavaScript
-
本文演示了如何在 JavaScript 中验证 Google Recaptcha。
C# 中的 goto 语句
发布时间:2024/02/02 浏览次数:184 分类:编程语言
-
本教程演示了如何在 C# 中使用 goto 以及何时使用它会有所帮助本教程将演示如何在 C# 中使用 goto 语法,并提供一些代码中的实际使用示例。
在 Python 中是否存在 goto 语句
发布时间:2023/12/20 浏览次数:197 分类:Python
-
本文为你提供了 Python 中是否存在 goto 语句的答案。本文为你提供了 Python 中是否存在 goto 语句的答案。基本上,Python 不支持 goto 语句。
避免 Python中的 TypeError: Input Expected at Most 1 Argument, Got 3 错误
发布时间:2023/07/08 浏览次数:671 分类:Python
-
Python 中避免 TypeError: input Expected atmost 1 argument, got 3 Error在Python编程中,我们有两个内置方法来获取用户的输入:input(prompt)和 raw_input(prompt)。
使用 Python 将文件上传到 Google 云端硬盘
发布时间:2023/06/15 浏览次数:544 分类:Python
-
本文将介绍我们如何使用 Python 将文件上传到云盘,以 Google Drive 为例。 为此,我们将使用 Google Drive API。
Python 错误 Valueerror: Expected 2d Array, Got 1d Array Instead
发布时间:2023/05/30 浏览次数:293 分类:Python
-
当我们在 numpy 中传递一维数组而不是二维数组时,会发生错误 ValueError: Expected 2D array, got 1D array instead 。如您所知,每种编程语言都会遇到很多错误,有些是在运行时,有些是在编译时。 Pyth