理解Go语言中的defer

引言

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

相关推荐

  1. 理解Go语言defer

    2023-12-11 19:02:02       62 阅读
  2. Go】探索Go语言关于defer应用

    2023-12-11 19:02:02       45 阅读
  3. 理解Go语言竞争问题

    2023-12-11 19:02:02       35 阅读
  4. Go语法之函数 defer使用

    2023-12-11 19:02:02       43 阅读
  5. 深入理解Go语言Channel与Select

    2023-12-11 19:02:02       48 阅读
  6. Godefer看似很简单,实则一点都不难

    2023-12-11 19:02:02       28 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-11 19:02:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-11 19:02:02       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-11 19:02:02       82 阅读
  4. Python语言-面向对象

    2023-12-11 19:02:02       91 阅读

热门阅读

  1. 初次参加软考就想报高级,哪个相对容易考?

    2023-12-11 19:02:02       71 阅读
  2. C++可以函数重载而C不可以的原因

    2023-12-11 19:02:02       55 阅读
  3. Springboot 集成 RocketMq5+ (gRPC 协议)

    2023-12-11 19:02:02       79 阅读
  4. 8-Hive原理与技术

    2023-12-11 19:02:02       54 阅读
  5. 【影像组学入门百问】1#---#3

    2023-12-11 19:02:02       69 阅读
  6. Linux文本格式命令 set ff

    2023-12-11 19:02:02       152 阅读
  7. 如何预防最新的.halo勒索病毒感染您的计算机?

    2023-12-11 19:02:02       55 阅读
  8. ATM的转账

    2023-12-11 19:02:02       83 阅读