Go语言 在for循环中调用defer-是否有更好的方法延迟从通道阅读响应?[duplicate]

kx5bkwkv  于 2023-03-10  发布在  Go
关注(0)|答案(1)|浏览(458)

此问题在此处已有答案

Proper way to release resources with defer in a loop?(3个答案)
5小时前关门了。
我正在尝试调用一个函数,该函数在循环中返回一个通道。然后,该通道被附加到切片channelSlice上。最后,该通道切片被迭代并打印每个通道的响应。在我执行此操作时,我的IDE显示一个警告:

Possible resource leak, 'defer' is called in the 'for' loop

正如您所看到的,我在第二个for循环中调用了close(channelSlice[i])。不推荐这样做吗?还有,这怎么会导致资源泄漏呢?有没有更好的方法来处理通道的关闭或切片?

package main

import (
    "fmt"
    "math/rand"
)

func t() chan int {
    c := make(chan int)
    go func() {
        c <- rand.Intn(100)
    }()

    return c
}

func main() {
    channelSlice := make([]chan int, 0)
    for i := 0; i<100; i++ {
        // Keep making concurrent calls
        // Will read responses from the channel later
        channelSlice = append(channelSlice, t())
    }

    for i := 0; i<100; i++ {
        defer close(channelSlice[i]) // Warning thrown by IDE
        fmt.Println(<-channelSlice[i])
    }
}
h7appiyu

h7appiyu1#

正如@mkopriva所指出的,
延迟调用在周围的函数退出时执行,在周围的非函数块退出时不被调用。用闭包将循环体括起来。
我是这么做的:

for i := 0; i<100; i++ {
        func() {
            defer close(channelSlice[i])
            fmt.Println(<-channelSlice[i])
        }()
    }

如您所见,我将defer语句 Package 在IIFE(立即调用函数表达式)中,使其成为闭包也是很好的。
这确保了通道现在将被关闭,并且不会有内存泄漏。

相关问题