日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Go 知识点(09)— for select 作用于 channel

發布時間:2023/11/28 生活经验 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go 知识点(09)— for select 作用于 channel 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. for select 作用于未關閉的通道

1.1 沒有 default 分之場景

先看下面代碼

func main() {ch := make(chan int, 3)go func() {time.Sleep(2 * time.Second) // 延遲往通道里里面發送數據ch <- 1}()for {select {case v, ok := <-ch:fmt.Printf("v=%v, ok=%v\n", v, ok)time.Sleep(1 * time.Second)}fmt.Println("waiting")}
}

執行代碼輸出結果如下:

v=1, ok=true
waiting
fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan receive]:
main.main()/home/wohu/project/go/src/demo/demo.go:17 +0x82
exit status 2

從結果我們可以看到:

  • 當通道中沒有數據時,且 select 語句沒有 default 分之時,會一直阻塞在 case 語句中;
  • 當通道中有數據時,case 語句拿到通道里面的值之后,繼續執行 select 語句塊之外的其余 for 循環體語句;
  • 當通道里面的數據被取走之后,case 語句一直等待從通道中取數據,但是一直沒有數據發送過來就會造成死鎖;

怎么避免這個死鎖問題呢? 這就需要加上 default 分之了。

1.2 有 default 分之場景

查看下面代碼

func main() {ch := make(chan int, 3)go func() {time.Sleep(2 * time.Second) // 延遲往通道里里面發送數據ch <- 1}()for {select {case v, ok := <-ch:fmt.Printf("v=%v, ok=%v\n", v, ok)time.Sleep(1 * time.Second)default:fmt.Println("通道沒有數據")time.Sleep(1 * time.Second)}fmt.Println("waiting")}
}

運行代碼輸出結果如下:

通道沒有數據
waiting
通道沒有數據
waiting
v=1, ok=true
waiting
通道沒有數據
waiting
通道沒有數據

從結果我們可以看到:

  • 當通道中沒有數據時,走 default 分之,default 分之完成后會繼續執行 for 循環體的其它語句;
  • 當通道中有數據,則會執行對應的 case 分之;
  • 當通道再一次沒有數據時,則繼續會執行 default 分之和剩余的其它for 循環體語句,而且會一直死循環執行;

2. for select 作用于關閉的通道

2.1 對關閉的通道執行 case 會造成死循環

繼續下面代碼

func main() {ch := make(chan int, 3)go func() {time.Sleep(2 * time.Second) // 延遲往通道里里面發送數據ch <- 1close(ch)}()for {select {case v, ok := <-ch:fmt.Printf("v=%v, ok=%v\n", v, ok)time.Sleep(1 * time.Second)default:fmt.Println("通道沒有數據")time.Sleep(1 * time.Second)}fmt.Println("waiting")}
}

運行輸出結果

通道沒有數據
waiting
通道沒有數據
waiting
v=1, ok=true
waiting
v=0, ok=false
waiting
v=0, ok=false
...

注意我們在前面已經將通道關閉,這個時候的 case 語句依然成立,所以會形成死循環執行這個 case 語句。

那么怎樣能跳出這個死循環的 case 語句呢?

2.2 跳出死循環的 case 語句

要跳出這個死循環的 case 語句,我們需要在 case 中通過第二個參數判斷 chan 是否關閉,如果關閉則通過 make(chan type) 來將關閉的 channil ,當再次執行到 select 時,因為 channil 會進入阻塞。

select 中如果任意某個分之可讀(包括 default ),它就會被執行,其他被忽略。所以在有 default 分之場景時, select 會跳過這個阻塞 case ,去執行 default 分之,這樣就可以避開這個死循環的 case 分之。

func main() {ch := make(chan int, 3)go func() {time.Sleep(2 * time.Second) // 延遲往通道里里面發送數據ch <- 1close(ch)}()for {select {case v, ok := <-ch:if !ok {ch = make(chan int)fmt.Println("通道已經關閉")} else {fmt.Printf("v=%v, ok=%v\n", v, ok)time.Sleep(1 * time.Second)}default:fmt.Println("通道沒有數據")time.Sleep(1 * time.Second)}fmt.Println("waiting")}
}

輸出結果如下:

通道沒有數據
waiting
通道沒有數據
waiting
v=1, ok=true
waiting
通道已經關閉
waiting
通道沒有數據
waiting
...

會一直循環打印 default 分之的輸出,那怎樣跳出這個循環呢?

2.3 跳出 for select 循環語句

  • 可以使用 gotolable 跳轉到 for 外面;
  • 可以設置一個額外的標記位,當 chan 關閉時,設置 flag=true ,在 for 的最后判斷 flag 決定是否 break

我們采用第二種方案:

func main() {ch := make(chan int, 3)go func() {time.Sleep(2 * time.Second) // 延遲往通道里里面發送數據ch <- 1close(ch)}()exitFlag := falsefor {select {case v, ok := <-ch:if !ok {ch = make(chan int)fmt.Println("通道已經關閉")exitFlag = true} else {fmt.Printf("v=%v, ok=%v\n", v, ok)time.Sleep(1 * time.Second)}default:fmt.Println("通道沒有數據")time.Sleep(1 * time.Second)}if exitFlag {fmt.Println("跳出循環")break}fmt.Println("waiting")}
}

輸出結果

通道沒有數據
waiting
通道沒有數據
waiting
v=1, ok=true
waiting
通道已經關閉
跳出循環

由以上示例我們可以得出以下結論:

  1. select 語句中如果任意某個 case 的通道有值可讀時,它就會被執行,其他 case 會被忽略;
  2. 如果沒有 default 語句,select 將有可能阻塞,直到某個 case 分之有值可以運行,所以 select 里最好有一個 default ,否則將有一直阻塞的風險;

如果 select 語句發現同時有多個候選分支滿足選擇條件,那么它就會用一種偽隨機的算法在這些分支中選擇一個并執行。

僅當 select 語句中的所有 case 表達式都被求值完畢后,它才會開始選擇候選分支。這時候,它只會挑選滿足選擇條件的候選分支執行。如果所有的候選分支都不滿足選擇條件,那么默認分支就會被執行。如果這時沒有默認分支,那么 select 語句就會立即進入阻塞狀態,直到至少有一個候選分支滿足選擇條件為止。一旦有一個候選分支滿足選擇條件,select 語句就會被喚醒,這個候選分支就會被執行。

總結

以上是生活随笔為你收集整理的Go 知识点(09)— for select 作用于 channel的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 伊人啪啪网 | 日韩欧美网站 | 性色av一区二区三区红粉影视 | 亚洲精品乱码久久久久 | 在线免费观看一区二区 | 在线观看免费的av | 午夜精品久久久久久久99老熟妇 | 毛片av免费看 | 国产大片黄 | 97精品久久| 欧美bbbbbbbbbbbb1 麻豆精品av | 动漫美女无遮挡免费 | 中文字幕久久网 | www.在线观看av | 国产精品suv一区二区88 | 国产在线免费 | av最新在线 | 国产精品第12页 | 成人一区二区三区在线 | 麻豆传媒一区 | 亚洲欧美日韩在线不卡 | 亚欧美色图 | 91视频免费网址 | 视频久久 | 亚洲精品视频专区 | 欧美xxxⅹ性欧美大片 | 一色桃子juy758在线播放 | 噜噜吧噜噜色 | 免费在线看污视频 | 国产探花在线精品一区二区 | 色婷婷中文字幕 | 性歌舞团一区二区三区视频 | 小香蕉av | 麻豆视频在线观看免费 | 亚洲av无码一区二区三区性色 | 一区二区三区四区中文字幕 | 日韩在线视频播放 | 日韩黄色免费电影 | 一区二区三区影院 | 人成午夜 | 91欧美日韩 | 亚洲国产一区二区在线观看 | 高清视频免费在线观看 | 影音先锋中文字幕在线视频 | 久久福利影院 | 欧美一区久久 | 成人av小说| 黑人粗进入欧美aaaaa | 久99精品 | 无码h肉动漫在线观看 | 亚洲一级av无码毛片精品 | 中文字幕影片免费在线观看 | 欧美日韩中文国产 | 精品黑人一区二区三区观看时间 | 日韩欧美精品在线播放 | 91精品国产99久久久久久 | 99国产精品久久久久99打野战 | 日本性爱动漫 | 你懂的在线网站 | 丁香在线 | 中文字幕被公侵犯的漂亮人妻 | 国内自拍视频在线播放 | 国产一区二区欧美 | 欧美精品91 | 精品少妇人妻av免费久久久 | 国产又黄又嫩又滑又白 | 一道本在线视频 | 欧美日韩加勒比 | 日本一区二区三区久久久久 | 大桥未久恸哭の女教师 | 午夜av免费看 | 三级影片在线免费观看 | 亚洲香蕉中文网 | 日韩无遮挡 | 窝窝午夜看片 | 少妇高潮一区二区三区99小说 | 男人和女人日b视频 | 久久成人免费网站 | 精品影视一区二区 | 日韩成人精品一区 | 懂色av一区二区三区四区 | 国产xx视频 | 免费在线观看av | 91久操 | 一区二区三区视频在线观看 | 自拍视频一区 | 欧美午夜性春猛交 | 免费成人结看片 | 在线观看的网站 | 日本一区中文 | 亚洲色图20p| 国产九九九 | 中文在线永久免费观看 | 无码无遮挡又大又爽又黄的视频 | av网页在线观看 | 国产欧美日韩精品区一区二污污污 | 免费av播放 | 超碰在线伊人 | 看了下面会湿的视频 |