-1

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])
    }
}
Suhail Gupta
  • 22,386
  • 64
  • 200
  • 328
  • 2
    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. – mkopriva Mar 10 '23 at 06:41
  • @mkopriva Added an answer. But used `IIFE`. – Suhail Gupta Mar 10 '23 at 06:49

1 Answers1

0

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.

Suhail Gupta
  • 22,386
  • 64
  • 200
  • 328
  • 1
    Just to clarify, in your specific example, there actually isn't any real problem, there is no leak. However `defer` statements inside loops _can_ cause leaks, specifically in cases where the call's arguments are pointers whose pointed-to values are being updated on each iteration. – mkopriva Mar 10 '23 at 06:54