📜  Golang 中的 Defer 关键字(1)

📅  最后修改于: 2023-12-03 14:41:33.779000             🧑  作者: Mango

Golang 中的 Defer 关键字

在 Golang 中,defer 是一种用于推迟(或延后)函数的执行的关键字。使用 defer 可以将函数的执行推迟到当前函数返回时或者当前包含该函数的函数体执行完毕时。

基本语法

使用 defer 的基本语法如下:

defer 函数名(参数列表)

defer 后面紧跟的是一个函数的调用语句,可以带有参数列表。当函数执行到 defer 语句时,该语句后面的函数调用不会立即执行,而是被推迟到函数返回时才会执行。

执行顺序

在一个函数中,可以使用多个 defer 语句。这些被推迟执行的函数调用将按照后进先出的顺序执行,也就是说最后一个被调用的 defer 语句将最先执行,而第一个 defer 语句将最后执行。

package main

import "fmt"

func main() {
    defer fmt.Println("第三个被执行的defer语句")
    defer fmt.Println("第二个被执行的defer语句")
    defer fmt.Println("第一个被执行的defer语句")

    fmt.Println("函数体内正常执行的语句")
}

输出结果:

函数体内正常执行的语句
第一个被执行的defer语句
第二个被执行的defer语句
第三个被执行的defer语句
使用场景
文件操作

在处理文件时,使用 defer 可以确保在函数返回前关闭打开的文件,避免资源泄漏。

package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("file.txt")
    if err != nil {
        fmt.Println("打开文件失败:", err)
        return
    }
    defer file.Close()

    // 处理文件
}
锁操作

在使用互斥锁进行并发控制时,使用 defer 可以确保在函数执行完毕后释放锁,避免死锁。

package main

import (
    "fmt"
    "sync"
)

var counter int
var mutex sync.Mutex

func main() {
    for i := 0; i < 10; i++ {
        go increment()
    }

    // 等待所有 goroutine 执行完成
    time.Sleep(time.Second)

    fmt.Println("counter:", counter)
}

func increment() {
    defer mutex.Unlock()

    mutex.Lock()
    counter++
}
清理操作

在需要进行一些清理操作时,使用 defer 可以保证在函数返回前执行这些清理操作。

package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("file.txt")
    if err != nil {
        fmt.Println("打开文件失败:", err)
        return
    }
    defer func() {
        file.Close()
        os.Remove("file.txt")
    }()

    // 处理文件
}

在上述示例中,无论函数在何处返回,都可以确保文件被关闭并且被删除。

总结

defer 关键字用于推迟函数的执行,以确保在函数返回前执行一些必要的操作。它可以应用于多种场景,如文件操作、锁操作和清理操作。使用 defer 可以让代码更加简洁、清晰,并避免一些常见的错误。