在Go中使用defer [英] Use of defer in Go
问题描述
defer
在Go中的用途是什么?语言文档说它在周围的函数返回时执行.为什么不将代码放在给定函数的末尾?
What is the use of defer
in Go? The language documentation says it is executed when the surrounding function returns. Why not just put the code at end of given function?
推荐答案
我们通常使用defer
关闭或释放资源.
We usually use defer
to close or deallocate resources.
周围的函数会在返回前执行所有延迟的函数调用,即使它会死机.如果只是将函数调用放在周围函数的末尾,则在发生紧急情况时会跳过该调用.
A surrounding function executes all deferred function calls before it returns, even if it panics. If you just place a function call at the end of a surrounding function, it is skipped when panic happens.
此外,延迟的函数调用可以通过调用recover
内置函数来处理紧急情况.这不能通过在函数末尾进行普通函数调用来完成.
Moreover a deferred function call can handle panic by calling the recover
built-in function. This cannot be done by an ordinary function call at the end of a function.
每个延迟调用都放在堆栈上,并在周围函数结束时以相反的顺序执行.颠倒顺序有助于正确分配资源.
Each deferred call is put on stack, and executed in reverse order when the surrounding function ends. The reversed order helps deallocate resources correctly.
要调用一个函数,必须达到defer
语句.
The defer
statement must be reached for a function to be called.
您可以将其视为实现try-catch-finally
块的另一种方式.
You can think of it as another way to implement try-catch-finally
blocks.
像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相比,好处是没有块和变量作用域的嵌套.这简化了周围功能的结构.
The benefit over try-catch-finally is that there is no nesting of blocks and variable scopes. This simplifies the structure of the surrounding function.
就像finally块一样,如果延迟函数调用可以到达返回的数据,则它们也可以修改返回值.
Just like finally blocks, deferred function calls can also modify the return value if they can reach the returned data.
func yes() (text string) {
defer func() {
text = "no"
}()
return "yes"
}
func main() {
fmt.Println(yes())
}
这篇关于在Go中使用defer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!