理解Go语言中的defer

2023-12-15 08:30:50

引言

Go有许多在其他编程语言中可以找到的常见控制流关键字,例如ifswitchfor等。defer是其他大多数编程语言中没有的关键字,尽管它不太常见,但你很快就会看到它在你的程序中有多么有用。

defer语句的主要用途之一是清理资源,例如打开的文件,网络连接和数据库句柄。在程序使用完这些资源后,关闭它们是很重要的,以避免耗尽程序的限制,并允许其他程序访问这些资源。通过将关闭文件/资源的调用保持在接近open调用的位置,defer使我们的代码更清晰,更不容易出错。

在本文中,我们将学习如何正确使用defer语句来清理资源,以及在使用defer时所犯的几个常见错误。

什么是defer语句

defer语句将defer关键字后面的[function]调用添加到栈上。当添加它们的函数返回时,该堆栈上的所有调用都会被调用。因为这些调用是放在栈上的,所以它们是按照后进先出的顺序调用的。

让我们通过打印一些文本来看看defer是如何工作的:

main.go

package main

import "fmt"

func main() {
   
	defer fmt.Println("Bye")
	fmt.Println("Hi")
}

main函数中,我们有两个语句。第一个语句以defer关键字开始,接着是print语句,打印出Bye。下一行打印出Hi

如果运行这个程序,会看到如下输出:

OutputHi
Bye

注意,首先打印的是Hi。这是因为任何以defer关键字开头的语句直到使用defer的函数结束时才会被调用。

再看一下这个程序,这次我们将添加一些注释来帮助解释所发生的事情:

main.go

package main

import "fmt"

func main() {
   
	// defer statement is executed, and places
	// fmt.Println("Bye") on a list to be executed prior to the function returning
	defer fmt.Println("Bye")

	// The next line is executed immediately
	fmt.Println("Hi")

	// fmt.Println*("Bye") is now invoked, as we are at the end of the function scope
}

理解defer的关键是,当defer语句执行时,延迟函数的参数会立即计算。当defer执行时,它将后面的语句放在一个列表中,以便在函数返回之前调用。

尽管这段代码说明了defer的运行顺序,但这并不是编写Go程序时使用它的典型方式。我们更有可能使用defer来清理资源,例如文件句柄。接下来让我们看看如何做到这一点。

使用defer来清理资源

在Go中使用defer来清理资源是很常见的。让我们首先来看一个程序,它将字符串写入文件,但不使用defer来处理资源清理:

main.go

package main

import (
	"io"
	"log"
	"os"
)

func main() {
   
	if err := write("readme.txt", "This is a readme file"); err != nil {
   
		log.Fatal("failed to write file:", err)
	}
}

func write(fileName string, text string) error {
   
	file, err := os.Create(fileName

文章来源:https://blog.csdn.net/QIU176161650/article/details/134868952
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。