理解Go语言中的defer
引言
Go有许多在其他编程语言中可以找到的常见控制流关键字,例如if
、switch
、for
等。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
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!