延迟函数调用

Go有一个称为defer的特殊语句,该语句计划在函数完成后运行函数调用。考虑以下示例:

package main
import "fmt"
func first() {
	fmt.Println("First")
}
func second() {
	fmt.Println("Second")
}
func main() {
	defer second()
	first()
}

该程序先打印“ First”,然后打印“ Second”。

延迟语句通常与成对的操作(例如打开和关闭,连接和断开连接或锁定和解锁)一起使用,以确保在所有情况下都释放资源,无论控制流程多么复杂。成功获取资源后,立即释放资源的defer语句的正确位置。

下面是打开文件并对文件执行读/写操作的示例。在这个例子中,经常有很多地方你想早点回来。

没有延迟

func ReadWrite() bool {
	file.Open("file")

	if failureX {
	file.Close()   //And here...
	return false
	}
	if failureY {
	file.Close()  //And here...
	return false
	}
	file.Close()  //And here...
	return true
}

这里重复很多代码。为了克服这一点,Go提供了defer语句。上面的代码可以按如下方式重写。这使函数更易读,更短,并将“关闭”置于“打开”旁边。

随着推迟

func ReadWrite() bool {
file.Open("file")
defer file.Close()   //file.Close() is added to defer list
// Do your thing
if failureX {
return false   // Close() is now done automatically
}
if failureY {
return false   // And here too
}
return true   // And here
}

这具有各种优点:

-将“关闭”电话保持在“打开”电话附近,因此更易于理解。
-如果我们的函数有多个return语句(如果在if中一个,在另一个else中一个),则关闭将在两个语句之前发生。
-即使发生运行时紧急情况,也会运行延迟功能。
-延迟功能以LIFO顺序执行,因此上面的代码打印为:4 3 2 1 0。
-您可以将多个功能放在“延迟列表”上,例如本例。

package main
import "fmt"
func main() {
	for i := 0; i < 5; i++ {
		defer fmt.Printf("%d ", i)
	}
}