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

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

Go 代碼示例未選擇“完成”情況?

Go 代碼示例未選擇“完成”情況?

Go
GCT1015 2023-07-26 19:47:53
改編為以下腳本:package mainimport (? ? "fmt"? ? "time")func main() {? ? ticker := time.NewTicker(500 * time.Millisecond)? ? done := make(chan bool)? ? go func() {? ? ? ? for {? ? ? ? ? ? select {? ? ? ? ? ? case <-done:? ? ? ? ? ? ? ? fmt.Println("Received 'done'")? ? ? ? ? ? ? ? return? ? ? ? ? ? case t := <-ticker.C:? ? ? ? ? ? ? ? fmt.Println("Tick at", t)? ? ? ? ? ? }? ? ? ? }? ? }()? ? time.Sleep(1600 * time.Millisecond)? ? // ticker.Stop()? ? done <- true? ? // fmt.Println("Ticker stopped.")}與引用示例的兩個區別是我注釋掉了該ticker.Stop()行并fmt.Println("Received 'done'")在case <-done塊中添加了一行。如果我運行它,我會觀察到以下輸出:> go run tickers.goTick at 2019-10-06 15:25:50.576798 -0700 PDT m=+0.504913907Tick at 2019-10-06 15:25:51.074993 -0700 PDT m=+1.003102855Tick at 2019-10-06 15:25:51.576418 -0700 PDT m=+1.504521538我的問題:為什么它不打印Received 'done'到終端?奇怪的是,如果我在Ticker stoppedPrintln 語句中發表評論,我也會看到Received 'done':> go run tickers.goTick at 2019-10-06 15:27:30.735163 -0700 PDT m=+0.504666656Tick at 2019-10-06 15:27:31.234076 -0700 PDT m=+1.003573649Tick at 2019-10-06 15:27:31.735342 -0700 PDT m=+1.504833296Ticker stopped.Received 'done'我記得,Goroutine 中的代碼可以假設同步運行,所以我很困惑,因為我沒有看到Println前一種情況下語句的效果,因為它發生在 Goroutine 返回之前。有人可以解釋一下嗎?去并發性協程
查看完整描述

2 回答

?
慕森王

TA貢獻1777條經驗 獲得超3個贊

發生時done <- true,main函數直接返回。


您可以添加另一個 time.Sleep() 來看看發生了什么。


    time.Sleep(1600 * time.Millisecond)

    // ticker.Stop()

    done <- true

    // fmt.Println("Ticker stopped.")

    time.Sleep(1600 * time.Millisecond)


查看完整回答
反對 回復 2023-07-26
?
SMILET

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

...為什么它不將 Received 'done' 打印到終端?

它確實這樣做了——或者更確切地說,它嘗試了。

當主 goroutine(調用mainpackage?main)返回時(或者在此處未發生的各種情況下更早),Go 程序就會退出。您致電并發送后main返回。time.Sleep()truedone

同時,當值到達通道時,循環中的 goroutinefor就會被喚醒。這是在主 Goroutine 發送之后發生的,之后主 Goroutine 正在退出。truedone

如果在這個退出過程中,主協程花費的時間足夠長,那么匿名協程就有時間打印Received 'done'。如果在這個退出過程中,主 Goroutine 足夠快,那么匿名 Goroutine 永遠不會完成,或者甚至永遠不會開始,打印任何東西,你什么也看不到。(實際輸出是由單個底層系統調用完成的,因此您要么獲得全部輸出,要么什么也得不到。)

您可以通過多種機制確保您派生的 goroutine 在主協程退出之前完成,但最簡單的可能是使用,sync.WaitGroup因為它就是為此設計的。創建一個 waitgroup,將其計數器設置為 1(將 1 添加到其初始零),然后Done在退出匿名 goroutine 時調用該函數。讓主協程等待它。


查看完整回答
反對 回復 2023-07-26
  • 2 回答
  • 0 關注
  • 161 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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