【Go】 语言中的 【defer】 关键字用法

在 Go 语言中,defer 关键字是一个非常强大的工具,常用于延迟函数的执行,通常用于确保在函数退出时进行清理工作,比如关闭文件、释放资源、解锁等。本文将详细介绍 defer 的用法、特点以及一些最佳实践。

什么是 defer

defer 关键字用于注册一个延迟调用,这个调用会在当前函数执行结束时执行。即使函数因为错误或其他原因提前退出,defer 注册的函数仍会被调用。

基本用法

defer functionName(arguments)

示例代码

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Start")
    defer fmt.Println("Deferred function executed")
    fmt.Println("End")
}

输出:

Start
End
Deferred function executed

在这个例子中,虽然 defer 语句位于 main 函数的中间部分,但它在函数结束时执行,因此 Deferred function executed 是最后输出的。

多个 defer 调用

如果在一个函数中有多个 defer 语句,它们会按照后进先出(LIFO)的顺序执行。这意味着最后一个 defer 语句会最先执行。

package main

import (
    "fmt"
)

func main() {
    defer fmt.Println("First defer")
    defer fmt.Println("Second defer")
    defer fmt.Println("Third defer")
    
    fmt.Println("Main function")
}

输出:

Main function
Third defer
Second defer
First defer

defer 的应用场景

1. 资源清理

defer 常用于在函数结束时释放资源,比如关闭文件或网络连接。以下是一个示例:

package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("test.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close() // 确保文件在函数结束时关闭

    // 在这里处理文件
    fmt.Println("File opened successfully")
}
2. 锁的解锁

在多线程编程中,defer 也常用于解锁,确保锁在函数结束时被释放,以避免死锁。

package main

import (
    "fmt"
    "sync"
)

var mu sync.Mutex

func criticalSection() {
    mu.Lock()
    defer mu.Unlock() // 确保在函数结束时释放锁
    fmt.Println("Inside critical section")
}

func main() {
    criticalSection()
}
3. 处理错误

在处理错误时,defer 可以用于记录错误信息或者进行一些收尾工作。

package main

import (
    "fmt"
)

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    
    fmt.Println("Starting")
    panic("Something went wrong") // 引发 panic
    fmt.Println("This line will not be executed")
}

性能注意事项

虽然 defer 非常方便,但在高性能的场景中,频繁使用 defer 可能会导致性能下降,因为每个 defer 调用都会有额外的开销。因此,在性能敏感的代码中,可以考虑手动调用函数而不是使用 defer

猜你喜欢

转载自blog.csdn.net/jhgj56/article/details/143152760