首頁 > 後端開發 > Golang > 在 for 迴圈中呼叫 defer - 是否有更好的方法來延遲從通道讀取回應?

在 for 迴圈中呼叫 defer - 是否有更好的方法來延遲從通道讀取回應?

王林
發布: 2024-02-09 12:15:22
轉載
1238 人瀏覽過

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

在 for 迴圈中呼叫 defer - 是否有更好的方法來延遲從通道讀取回應?這是許多開發者在使用 Go 語言時常遇到的問題。 defer 關鍵字在 Go 語言中用於延遲執行函數,在 for 迴圈中使用 defer 可以確保每次迴圈結束後都會執行某些操作。然而,如果需要在每次循環中從通道讀取回應,使用 defer 可能並不是最佳的選擇。那麼,是否有更好的方法來延遲從通道讀取回應?讓我們一起來探討一下。

問題內容

我正在嘗試呼叫一個在循環中傳回通道的函數。然後將該通道附加到切片 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])
    }
}
登入後複製

解決方法

如@mkopriva指出的,

延遲呼叫在周圍函數退出時執行,當周圍非功能塊退出時不會呼叫它們。將循環體封裝在閉包中。

這是我所做的:

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

如您所見,我將 defer 語句包裝在 iife(立即呼叫函數表達式)中。讓它成為一個閉包也很好。

這確保了通道現在將關閉並且不會出現記憶體洩漏。

以上是在 for 迴圈中呼叫 defer - 是否有更好的方法來延遲從通道讀取回應?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板