deferGo 的用途是什么?语言文档说它在周围的函数返回时执行。为什么不将代码放在给定函数的末尾?
defer
我们通常defer用来关闭或释放资源。
周围的函数会在返回之前执行所有延迟的函数调用,即使它会慌乱。如果仅将函数调用放在周围函数的末尾,则在发生紧急情况时将跳过该调用。
而且,延迟函数调用可以通过调用recover内置函数来处理紧急情况。这不能通过函数结尾处的普通函数调用来完成。
recover
每个延迟的调用都放在堆栈中,并在周围函数结束时以相反的顺序执行。颠倒顺序有助于正确分配资源。
defer必须调用该语句才能调用函数。
您可以将其视为实现try-catch-finally块的另一种方法。
try-catch-finally
结束像try-finally:
try-finally
func main() { f, err := os.Create("file") if err != nil { panic("cannot create file") } defer f.Close() // no matter what happens here file will be closed // for sake of simplicity I skip checking close result fmt.Fprintf(f,"hello") }
结束和恐慌处理,例如 try-catch-finally
func main() { defer func() { msg := recover() fmt.Println(msg) }() f, err := os.Create(".") // . is a current directory if err != nil { panic("cannot create file") } defer f.Close() // no matter what happens here file will be closed // for sake of simplicity I skip checking close result fmt.Fprintf(f,"hello") }
与try-catch-finally相比,好处是没有块和变量作用域的嵌套。这简化了周围功能的结构。
就像finally块一样,如果延迟函数调用可以到达返回的数据,则它们也可以修改返回值。
func yes() (text string) { defer func() { text = "no" }() return "yes" } func main() { fmt.Println(yes()) }