【Go】探索Go语言中的关于defer的应用


冬来的秋去
像记忆裂痕
又再变更空枕触遗憾
半梦半醒侵沾眼晴的泪痕
每晚夜深妄想真情接近
绻梦绻恋一宵雨侵悲不禁
永远最相衬
但愿梦里是永恒
——《永远之后-黄艺明》


在Go语言中,defer语句是一个非常强大且常用的特性,它允许我们在函数结束时执行一些清理操作或者确保某些代码在函数执行结束前被执行。本文将探讨defer语句的基本概念、使用案例以及在不同场景下的应用,包括读写文件和Go并发编程中的使用。

defer栈的概念

在了解defer语句的使用之前,首先需要了解defer栈的概念。在Go语言中,当一个函数中包含多个defer语句时,这些defer语句将按照后进先出(LIFO)的顺序执行。这意味着最后一个被defer的语句将会最先执行,而最先被defer的语句将会最后执行。

使用案例

读写文件

func readFile(filename string) ([]byte, error) {
    file, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    defer file.Close() // 确保在函数返回前关闭文件

    data, err := ioutil.ReadAll(file)
    if err != nil {
        return nil, err
    }
    return data, nil
}

在这个例子中,defer语句确保了在函数返回前关闭了打开的文件,无论读取文件是否成功。
Go并发

func parallelTask() {
    var wg sync.WaitGroup
    defer wg.Wait() // 等待所有任务完成

    for i := 0; i < 10; i++ {
        wg.Add(1) // 将WaitGroup的计数器加1,表示有一个新的任务需要等待
        go func() {
            defer wg.Done() // 当任务完成时,将WaitGroup的计数器减1
            // 执行并发任务
        }()
    }
}

当在Go中执行并发任务时,有时我们需要等待所有的并发任务完成后再继续执行后续的代码。这种情况下,我们可以使用sync.WaitGroup来实现并发任务的等待。sync.WaitGroup提供了一种机制,可以等待一组goroutine执行完毕。
sync.WaitGroup是一个计数信号量,用于等待一组goroutine的结束。在函数开头,我们创建了一个WaitGroup实例wg。

使用wg.Add(1)WaitGroup的计数器加1,这表示有一个新的任务需要等待。在这个例子中,我们有10个任务,所以调用了10次wg.Add(1)

在每个goroutine的结尾,我们使用defer wg.Done()WaitGroup的计数器减1,表示一个任务已经完成。这样可以确保即使在goroutine执行过程中发生了错误,也能够保证计数器会被减少。

最后,通过defer wg.Wait()语句,我们将等待所有的任务完成。wg.Wait()会一直阻塞当前goroutine,直到WaitGroup的计数器减为0,即所有的任务都已经完成。此时,parallelTask()函数会继续执行后续的代码。
通过合理地使用sync.WaitGroup,我们可以在并发任务中实现等待,确保所有的任务都已经完成后再执行后续的操作,这对于处理并发任务的场景非常有用。

结语

通过本文的介绍,我们深入了解了defer语句在Go语言中的概念和应用。无论是文件操作还是并发编程,defer语句都是一种强大的工具,可以确保资源的及时释放和代码的清晰性。在编写Go代码时,合理地使用defer语句可以提高代码的可读性和可维护性,同时减少资源泄漏的可能性。

你可能感兴趣的:(Go,golang,开发语言,后端)