我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛
模拟兔子的一天:浅聊Go关键字defer
作者:千石
本文专栏:兔了个兔
支持作者:点赞、评论、收藏
一则小故事
(故事的代码实现见文末码上掘金)
有一只可爱的兔子,它生活在一个充满生机和活力的小村庄。兔子非常喜欢新春,每年都会热烈庆祝。然而,有一年,兔子在新春庆祝活动后忘记了关闭灯光,电费比平时贵很多。
兔子想通过程序来控制灯光的关闭,以防止自己忘记关灯,于是它决定学习一门编程语言,希望能找到一种解决问题的方法。它选择了 Go 语言,并快速学会了如何使用 Go 语言的 defer 关键字。
兔子通过使用 defer 关键字,很容易地解决了上述问题。在新春庆祝活动中,兔子在关闭灯光前,通过使用 defer 关键字将关闭灯光的代码推迟到了庆祝活动结束之后执行。
从此以后,兔子再也不用担心忘记关闭灯光的问题了!
正文
通过上面的这则小故事,我们可以看出,defer 关键字允许程序员将一个函数的执行推迟到函数结束时执行。接下来,让我们聊聊Go语言的defer关键字。
介绍defer
"defer" 是 Go 语言的一个关键字,它可以在函数结束前延迟执行一个语句。使用方法是在要延迟执行的语句前面加上 "defer",具体语法如下:
defer <expression>
它通常用于释放资源(如打开的文件),在程序结束前执行清理工作,或者在特定的代码块中执行必要的操作。"defer" 的执行顺序类似于栈的顺序,即后进先出(LIFO),最后被压入栈的语句会最先执行。
优点:
- 简化代码:defer关键字允许我们将重要的清理操作放在一个地方,从而使代码更简洁。
- 防止资源泄露:使用defer语句可以确保在函数结束时释放资源,避免内存泄漏等问题。
- 简化错误处理:defer关键字可以简化错误处理,在函数结束前执行清理操作,避免出现不必要的错误。
- 提高代码可读性:defer关键字可以使代码更具可读性,因为它把重要的操作统一放在一起,易于理解。
一些细节
参数
"defer" 语句的参数在被延迟执行时被计算,而不是在 "defer" 语句执行时。因此,如果参数是一个函数调用,它会在被延迟执行时立即调用。
package main
import "fmt"
func main() {
i := 1
defer fmt.Println("defer value:", func() int { return i * 2 }())
i++
fmt.Println("main value:", i)
// Output:
// main value: 2
// defer value: 2
}
参数作用域
"defer" 语句的参数在函数内可见,因此如果 "defer" 语句引用了外部变量,则变量的值将在 "defer" 语句被延迟执行时被计算。
package main
import "fmt"
func main() {
i := 1
defer fmt.Println("defer value:", i)
i++
fmt.Println("main value:", i)
// Output:
// main value: 2
// defer value: 1
}
在函数中的执行顺序
"defer" 语句在函数中按照后进先出(LIFO)的顺序执行,即最后被压入栈的语句最先执行。
package main
import "fmt"
func main() {
defer fmt.Println("defer 1")
defer fmt.Println("defer 2")
defer fmt.Println("defer 3")
fmt.Println("main")
// Output:
// main
// defer 3
// defer 2
// defer 1
}
在控制结构中的执行顺序
如果一个函数内包含多个控制结构(如循环),则 "defer" 语句在每个控制结构中都有自己的执行顺序,并且受该结构的范围限制。
package main
import "fmt"
func main() {
for i := 0; i < 3; i++ {
defer fmt.Println("defer in loop", i)
}
fmt.Println("main")
// Output:
// main
// defer in loop 2
// defer in loop 1
// defer in loop 0
}
一些🌰
- 资源释放:
func ReadFile(filename string) {
file, err := os.Open(filename)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
// 读取文件
// ...
}
在这个例子中,我们使用defer语句确保文件在函数结束时被关闭。
- 延迟初始化:
func init() {
// 延迟初始化
defer fmt.Println("Init complete.")
}
在这个例子中,我们使用defer语句实现延迟初始化。
- 错误处理:
func handleError(err error) {
defer fmt.Println("Error handled.")
if err != nil {
// 处理错误
// ...
}
}
在这个例子中,我们使用defer语句确保错误被处理并且消息被打印。
最后
总结
本文详细介绍了Go语言的defer关键字,包括它的定义、语法、作用以及实际应用。defer关键字是Go语言中一种非常有用的特性,它可以简化代码,防止资源泄露,简化错误处理,提高代码可读性。
创作不易,如果你觉得本文对你有帮助,可以点赞、评论、收藏,你的支持是我最大的动力,下次更新会更快!
最后,祝大家兔年快乐!
码上掘金