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

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

Golang 入站通道未在 goroutine 內接收

Golang 入站通道未在 goroutine 內接收

Go
郎朗坤 2021-08-10 15:34:56
請幫助我理解為什么<-done在這種情況下沒有接收入站頻道?func main() {    done := make(chan bool)    println("enter")    defer func() {        println("exit")    }()    defer func() {        println("  notify start")        done <- true        println("  notify end")    }()         go func() {        println("    wait start")        <-done        println("    wait end")    }()    time.Sleep(time.Millisecond) // << when this is removed, it works.}我期待輸出是:enter  notify start    wait start    wait end  notify endexit但它是:enter    wait start  notify start  notify endexit我最初假設done通道以某種方式被提前關閉或清理,但即使done是全局的,它也會導致相同的意外行為。不應該<-done阻塞直到done <- true發生?反之亦然?解決似乎我期望程序在退出之前等待所有 goroutine 完成。這是一個錯誤的假設。這是一個骯臟的解決方法:func main() {    done, reallydone := make(chan bool), make(chan bool)    println("enter")    defer func() {        <-reallydone        println("exit")    }()    go func() {        println("    wait start")        <-done        println("    wait end")        reallydone <- true    }()    defer func() {        println("  notify start")        done <- true        println("  notify end")    }()    time.Sleep(time.Millisecond)}
查看完整描述

2 回答

?
梵蒂岡之花

TA貢獻1900條經驗 獲得超5個贊

當您使用 sleep 時,它為 goroutine 提供時間啟動,然后當它從通道讀取時, main 在最后一個println("    wait end")被調用之前退出。


但是,如果您不調用 sleep,defer 將阻塞,直到 goroutine 從中讀取并為其提供足夠的時間進行打印。


如果您將代碼移動到不同的函數并從 main 調用它,它將按預期工作。


func stuff() {

    done := make(chan bool)

    println("enter")

    defer func() {

        println("exit")

    }()

    go func() {

        println("    wait start")

        <-done

        println("    wait end")

    }()

    defer func() {

        println("  notify start")

        done <- true

        println("  notify end")

    }()

}

func main() {

    stuff()

}


查看完整回答
反對 回復 2021-08-10
?
慕容708150

TA貢獻1831條經驗 獲得超4個贊

done通道上的事件序列:“[當] 通道無緩沖時,只有當發送方和接收方都準備好時,通信才會成功。” 對于你的例子,


的done信道是無緩沖:main。


done := make(chan bool)

接收等待發送:go func()。


<-done 

接收就緒 ( <-done),發送:defer func()。


done <- true

該main函數結束,不等待夠程(go func())結束。


輸出:


enter

    wait start

  notify start

  notify end

exit

Go 編程語言規范

渠道類型

通道為并發執行函數提供了一種機制,通過發送和接收指定元素類型的值來進行通信。未初始化通道的值為 nil。

可以使用內置函數 make 創建一個新的初始化通道值,該函數將通道類型和可選容量作為參數:

make(chan int, 100)

容量(以元素數為單位)設置通道中緩沖區的大小。如果容量為零或不存在,則通道沒有緩沖,只有當發送方和接收方都準備好時,通信才能成功。否則,如果緩沖區未滿(發送)或非空(接收),則通道被緩沖并且通信成功而不會阻塞。一個 nil 通道永遠不會準備好進行通信。

Go 語句

程序執行首先初始化主包,然后調用函數 main。當該函數調用返回時,程序退出。它不會等待其他(非主)goroutine 完成。


查看完整回答
反對 回復 2021-08-10
  • 2 回答
  • 0 關注
  • 263 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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