英文:
Calling defer in the for loop - Is there a better way to defer reading response from channels?
问题
我正在尝试在循环中调用一个返回通道的函数。然后将该通道附加到切片channelSlice
上。最后,迭代通道切片并打印每个通道的响应。在执行此操作时,我的IDE显示一个警告:
可能存在资源泄漏,'defer'在'for'循环中被调用
正如你所看到的,我在第二个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++ {
// 不断进行并发调用
// 稍后将从通道中读取响应
channelSlice = append(channelSlice, t())
}
for i := 0; i<100; i++ {
defer close(channelSlice[i]) // IDE抛出的警告
fmt.Println(<-channelSlice[i])
}
}
英文:
I am trying to call a function that returns a channel in a loop. The channel is then appended onto a slice channelSlice
. At the end, the channel slice is iterated and the response from each channel is printed. While I do this, my IDE shows a warning:
Possible resource leak, 'defer' is called in the 'for' loop
As you could see, I call close(channelSlice[i])
inside the second for loop. Is this not recommended? Also, how could this lead to a resource leak? Is there a better way to handle close or slice of channels?
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])
}
}
答案1
得分: 0
根据@mkopriva的指示,
延迟调用在包围函数退出时执行,而不是在包围非函数块退出时调用。将循环的主体封装在闭包中。
这是我所做的:
for i := 0; i<100; i++ {
func() {
defer close(channelSlice[i])
fmt.Println(<-channelSlice[i])
}()
}
正如你所看到的,我将defer
语句包装在了一个IIFE(立即调用的函数表达式)中。将其作为闭包也是可以的。
这确保了通道现在将被关闭,不会出现内存泄漏。
英文:
As pointed by @mkopriva,
> Deferred calls are executed when the surrounding function exits, they are not called when the surrounding non-function block exits. Enclose the loop's body in a closure.
Here is what I did:
for i := 0; i<100; i++ {
func() {
defer close(channelSlice[i])
fmt.Println(<-channelSlice[i])
}()
}
As you could see, I wrapped the defer
statement in a IIFE (Immediately Invoked Function Expression). Making it a closure would be fine as well.
This ensures, that the channel will now be closed and there will not be a memory leak.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论