第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

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

帶有for循環(huán)的goroutine內(nèi)部的“選擇”語句

帶有for循環(huán)的goroutine內(nèi)部的“選擇”語句

Go
慕妹3146593 2023-04-04 15:25:37
有人可以解釋一下,為什么如果 goroutine 有無限for循環(huán)并且select在循環(huán)內(nèi)部,循環(huán)中的代碼只運(yùn)行一次?package mainimport (    "time")func f1(quit chan bool){    go func() {        for {            println("f1 is working...")            time.Sleep(1 * time.Second)            select{            case <-quit:            println("stopping f1")            break            }        }       }()}func main() {    quit := make(chan bool)    f1(quit)    time.Sleep(4 * time.Second)}輸出:f1 is working...Program exited.但是如果“select”被注釋掉:package mainimport (    "time")func f1(quit chan bool){    go func() {        for {            println("f1 is working...")            time.Sleep(1 * time.Second)            //select{            //case <-quit:            //println("stopping f1")            //break            //}        }       }()}func main() {    quit := make(chan bool)    f1(quit)    time.Sleep(4 * time.Second)}輸出:f1 is working...f1 is working...f1 is working...f1 is working...f1 is working...https://play.golang.org/p/MxKy2XqQlt8
查看完整描述

1 回答

?
MMMHUHU

TA貢獻(xiàn)1834條經(jīng)驗 獲得超8個贊

select沒有 case 的語句是default阻塞case,直到可以執(zhí)行至少一個語句中的讀取或?qū)懭搿R虼?,?code>select將阻塞,直到可以從通道讀取quit(如果通道關(guān)閉,則為值或零值)。語言規(guī)范提供了對此行為的具體描述,特別是:

如果一個或多個通信[在陳述中表達(dá)case]可以繼續(xù),則通過統(tǒng)一的偽隨機(jī)選擇選擇一個可以繼續(xù)的通信。否則,如果存在默認(rèn)情況,則選擇該情況。如果沒有默認(rèn)情況,則“select”語句將阻塞,直到至少有一個通信可以繼續(xù)進(jìn)行。

其他代碼問題

警告!break適用于select聲明

但是,即使您確實關(guān)閉了quit通道以發(fā)出關(guān)閉程序的信號,您的實施也可能不會產(chǎn)生預(yù)期的效果。對 的(未標(biāo)記的)調(diào)用break將終止函數(shù)內(nèi)最內(nèi)層的fororselect語句switch的執(zhí)行。在這種情況下,select語句將中斷,for循環(huán)將再次運(yùn)行。如果quit被關(guān)閉,它將永遠(yuǎn)運(yùn)行直到其他東西停止程序,否則它將再次阻塞select

關(guān)閉quit將(可能)不會立即停止程序

正如time.Sleep所指出的,在循環(huán)的每次迭代中調(diào)用都會阻塞一秒鐘,因此任何通過關(guān)閉來停止程序的嘗試都會在 goroutine 檢查和退出quit之前延遲大約一秒鐘。quit在程序停止之前,這個睡眠周期不太可能必須完全完成。

更慣用的 Go 會在select從兩個渠道接收的語句中阻塞:

  • 頻道quit_

  • 返回的通道time.After– 此調(diào)用是圍繞 a 的抽象Timer,它會休眠一段時間,然后將值寫入提供的通道。

解決

更改最少的解決方案

通過對代碼進(jìn)行最少更改來解決您的直接問題的解決方案是:

  • 通過向語句添加默認(rèn)情況,使讀取成為quit非阻塞的select。

  • 確保 goroutine在讀取成功時實際quit返回:

    • 標(biāo)記for循環(huán)并使用標(biāo)記調(diào)用break;?或者

    • returnf1在需要退出時從函數(shù)中獲?。ㄊ走x)

根據(jù)您的情況,您可能會發(fā)現(xiàn) Go 更慣用地使用 a 來context.Context發(fā)出終止信號,并使用 async.WaitGroup等待 goroutine 在從 返回之前完成main

package main


import (

? ? "fmt"

? ? "time"

)


func f1(quit chan bool) {

? ? go func() {

? ? ? ? for {

? ? ? ? ? ? println("f1 is working...")

? ? ? ? ? ? time.Sleep(1 * time.Second)


? ? ? ? ? ? select {

? ? ? ? ? ? case <-quit:

? ? ? ? ? ? ? ? fmt.Println("stopping")

? ? ? ? ? ? ? ? return

? ? ? ? ? ? default:

? ? ? ? ? ? }

? ? ? ? }

? ? }()

}


func main() {

? ? quit := make(chan bool)

? ? f1(quit)

? ? time.Sleep(4 * time.Second)

? ? close(quit)

? ? time.Sleep(4 * time.Second)

}

工作示例

(注意:我在您的方法中添加了一個額外的time.Sleep調(diào)用main,以避免在調(diào)用close和終止程序后立即返回。)

修復(fù)睡眠阻塞問題

要解決有關(guān)阻止立即退出的阻塞睡眠的其他問題,請將睡眠移動到塊中的計時器select。for根據(jù)這個游樂場示例修改循環(huán)正是這樣做的:

for {

? ? println("f1 is working...")


? ? select {

? ? case <-quit:

? ? ? ? println("stopping f1")

? ? ? ? return

? ? case <-time.After(1 * time.Second):

? ? ? ? // repeats loop

? ? }

}


查看完整回答
反對 回復(fù) 2023-04-04
  • 1 回答
  • 0 關(guān)注
  • 142 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號