Home >Backend Development >Golang >Calling defer in a for loop - is there a better way to delay reading the response from the channel?

Calling defer in a for loop - is there a better way to delay reading the response from the channel?

王林
王林forward
2024-02-09 12:15:221209browse

在 for 循环中调用 defer - 是否有更好的方法来延迟从通道读取响应?

Calling defer in a for loop - is there a better way to delay reading the response from the channel? This is a common problem that many developers encounter when using the Go language. The defer keyword is used to delay the execution of functions in the Go language. Using defer in a for loop can ensure that certain operations are performed after each loop ends. However, if you need to read the response from the channel every loop, using defer may not be the best choice. So, is there a better way to delay reading the response from the channel? Let’s explore it together.

Question content

I'm trying to call a function that returns a channel in a loop. The channel is then attached to slice channelslice. Finally, iterate over the channel slices and print the response for each channel. When I do this, my IDE shows the warning:

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

As you can see, I'm calling close(channelslice[i]) inside the second for loop. Is this not recommended? Also, how could this cause a resource leak? Is there a better way to handle closing or slicing 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])
    }
}

Solution

As @mkopriva pointed out,

Delayed calls are executed when surrounding functions exit, they will not be called when surrounding non-functional blocks exit. Encapsulate the loop body in a closure.

This is what I did:

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

As you can see, I wrapped the defer statement in an iife (immediately invoked function expression). It would also be nice to make it a closure.

This ensures that the channel will now be closed and no memory leak will occur.

The above is the detailed content of Calling defer in a for loop - is there a better way to delay reading the response from the channel?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete