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])
}
}
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.