亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當您使用范圍通道中斷 for 語句時會發生什么

當您使用范圍通道中斷 for 語句時會發生什么

Go
www說 2022-06-21 16:09:12
我正在按照此代碼獲取帶有頻道的惰性數字范圍// iteratorfunc iterator(n int, c chan int) {    for i := 0; i < n; i++ {        c <- i    }    close(c)    fmt.Println("iterator End")}c := make(chan int)go iterator(5, c)for i := range c {    fmt.Println(i)}這將按預期打印01234fmt.Println("iterator End")但是當我像這樣打破for循環時發生了什么c := make(chan int)go getNumbers(5, c)for i := range c {    if i == 2 {        break    }    fmt.Println(i)}似乎 goroutine 被阻塞了,因為從不打印iterator End(我也嘗試通過休眠主線程)。我想知道如何處理這種情況?我需要用它select來解決這個問題嗎?有什么安全的方法可以檢查范圍是否中斷并停止迭代器中的for 循環?
查看完整描述

1 回答

?
慕的地6264312

TA貢獻1817條經驗 獲得超6個贊

如果一個 goroutine 寫入一個無緩沖的通道并且沒有其他 goroutine 從該通道讀取 - 那么寫入將永遠阻塞。這將導致 goroutine 泄漏。這就是你正在經歷的。


如果你有一個寫入通道的“生產者”goroutine,你需要一種方法來通知它停止。關閉通道不是這里的關鍵部分 - 因為通道超出范圍時會被垃圾收集。阻塞的 goroutine(永遠不會解除阻塞)被認為是泄漏,因為它永遠不會被回收,所以你真的需要 goroutine 結束。


您可以通過多種方式表示退出意圖 - 最受歡迎的兩種方式是:


一個done頻道;或者

context.Context取消

信號:完成通道

func iterator(n int, c chan int, done <-chan struct{}) {

    for i := 0; i < n; i++ {

        select {

        case c <- i:

        case <-done:

            break

        }

    }

    close(c)

    fmt.Println("iterator End")

}

閱讀器協程:


c := make(chan int)

done := make(chan struct{})

go iterator(5, c, done)

for i := range c {

    if i == 2 {

        break

    }

    fmt.Println(i)

}

close(done) // signal writer goroutine to quit

信號:context.Context

func iterator(ctx context.Context, n int, c chan int) {

        defer close(c)

        defer fmt.Println("iterator End")


        for i := 0; i < n; i++ {

                select {

                case c <- i:

                case <-ctx.Done():

                        fmt.Println("canceled. Reason:", ctx.Err())

                        return

                }

        }

}

閱讀 goroutine:


func run(ctx context.Context) {

        ctx, cancel := context.WithCancel(ctx)

        defer cancel()  // call this regardless - avoid context leaks - but signals producer your intent to stop

        c := make(chan int)

        go iterator(ctx, 5, c)

        for i := range c {

                if i == 2 {

                        break

                }

                fmt.Println(i)

        }

}

https://play.golang.org/p/4-fDyCurB7t


查看完整回答
反對 回復 2022-06-21
  • 1 回答
  • 0 關注
  • 106 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號