Grz*_*Żur 47
我们defer通常使用关闭或取消分配资源.保证在每种情况下运行.如有任何退货或恐慌.当您将功能放在最后时,您没有这种保证.
此外,一个deffered函数调用可以通过调用recover内置函数来处理恐慌.这不能通过最后的功能来完成.
您可以将其视为defer块的另一种实现.
结束一样 try-catch-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")
}
Run Code Online (Sandbox Code Playgroud)
关闭和恐慌处理都一样 try-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")
}
Run Code Online (Sandbox Code Playgroud)
try-catch-finally的好处是没有嵌套的块和可变范围简化了函数的结构.
类似于finally块,延迟函数调用也可以修改返回值,如果它们可以到达返回的数据.
func yes() (text string) {
defer func() {
text = "no"
}()
return "yes"
}
func main() {
fmt.Println(yes())
}
Run Code Online (Sandbox Code Playgroud)
May*_*yur 11
这里已经有很好的答案了。我想再提一个用例。
func BillCustomer(c *Customer) error {
c.mutex.Lock()
defer c.mutex.Unlock()
if err := c.Bill(); err != nil {
return err
}
if err := c.Notify(); err != nil {
return err
}
// ... do more stuff ...
return nil
}
Run Code Online (Sandbox Code Playgroud)
该defer在这个例子中可以确保无论怎样BillCustomer的回报时,mutex将unlocked之前立即BillCustomer返回。这是非常有用的,因为没有defer你就必须要记住unlock的mutex每一个地方,该功能可能可能return。
参考。
好吧,并不总是保证您的代码可能会到达函数的末尾(例如,错误或某些其他条件可能会迫使您在函数结束之前很早地返回)。defer 语句确保分配给它的任何函数都得到执行,即使函数发生混乱或代码在函数结束之前返回。
defer 语句还有助于保持代码干净,尤其是。在一个函数中有多个 return 语句的情况下。当一个人需要在返回之前释放资源时(例如,假设您在函数开始时有一个访问资源的开放调用 - 为此必须在函数返回之前调用相应的关闭以避免资源泄漏。并说您的函数有多个 return 语句,可能针对包括错误检查在内的不同条件。在这种情况下,如果没有延迟,您通常会在每个 return 语句之前调用该资源的 close)。defer 语句确保你传递给它的函数总是被调用,而不管函数在哪里返回,从而使你免于额外的内务工作。
也可以在同一个函数中多次调用 defer。例如:如果您通过函数分配了不同的资源,这些资源需要在返回之前最终释放,那么您可以在分配后为每个资源调用 defer,这些函数将按照与调用它们的顺序相反的顺序执行当函数退出时。
| 归档时间: |
|
| 查看次数: |
12641 次 |
| 最近记录: |