Golang併發模型 select高階

2021-09-07 08:48:35 字數 2446 閱讀 7342

最近公司工作有點多,golang的select高階就這樣被拖沓啦,今天堅持把時間擠一擠,把吹的牛皮補上。

前一篇文章《golang併發模型:輕鬆入門select》介紹了select的作用和它的基本用法,這次介紹它的3個高階特性。

nil的通道永遠阻塞

如何跳出for-selectselect{}阻塞

case上讀乙個通道時,如果這個通道是nil,則該case永遠阻塞。這個功能有1個妙用,select通常處理的是多個通道,當某個讀通道關閉了,但不想select再繼續關注此case,繼續處理其他case,把該通道設定為nil即可。

下面是乙個合併程式等待兩個輸入通道都關閉後才退出的例子,就使用了這個特性。

func

combine

(inch1, inch2

chan

int)

chan

int out

case x, open :=

if!open

out}

// 當ch1和ch2都關閉是才退出

if inch1 ==

nil&& inch2 ==

nil}}(

)return out

}

breakselect內的並不能跳出for-select迴圈。看下面的例子,consume函式從通道inch不停讀資料,期待在inch關閉後退出for-select迴圈,但結果是永遠沒有退出。

func

consume

(inch

chan

int)

fmt.

printf

("read: %d\n"

, x)

} i++

} fmt.

println

("combine-routine exit"

)}

執行結果:

➜ go run x.go

for: 0

read: 0

for: 1

read: 1

for: 2

read: 2

for: 3

gen exit

for: 4

for: 5

for: 6

for: 7

for: 8

... // never stop

既然break不能跳出for-select,那怎麼辦呢?給你3個錦囊:

在滿足條件的case內,使用return,如果有結尾工作,嘗試交給defer

selectfor內使用break挑出迴圈,如combine函式。

使用goto

select{}的效果等價於建立了1個通道,直接從通道讀資料:

ch :=

make

(chan

int)

但是,這個寫起來多麻煩啊!沒select{}簡潔啊。

但是,永遠阻塞能有什麼用呢!?

當你開發乙個併發程式的時候,main函式千萬不能在子協程幹完活前退出啊,不然所有的協程都被迫退出了,還怎麼提供服務呢?

比如,寫了個web服務程式,埠監聽、後端處理等等都在子協程跑起來了,main函式這時候能退出嗎?

最後,介紹下我常用的select場景:

給某個請求/處理/操作,設定超時時間,一旦超時時間內無法完成,則停止處理。

select本色:多通道處理

golang併發模型:輕鬆入門流水線模型

golang併發模型:輕鬆入門流水線fan模式

golang併發模型:併發協程的優雅退出

golang併發模型:輕鬆入門select

如果這篇文章對你有幫助,不妨關注下我的github,有文章會收到通知。

golang中的CSP併發模型

1.相關概念 使用者態 當乙個程序在執行使用者自己的 時處於使用者執行態 使用者態 核心態 當乙個程序因為系統呼叫陷入核心 中執行時處於核心執行態 核心態 引入核心態防止使用者態的程式隨意的操作核心位址空間,具有一定的安全保護作用。這種保護模式是通過記憶體頁表操作等機制,保證程序間的位址空間不會相互...

golang 閒談併發

對於併發這個概念,我想大家都對它不會陌生,今天就從簡單的火車站賣票問題出發,來談談併發。首先宣告本文的 是golang 因為最近開始用的就是golang 對於其他的語言其實也是相通的,那麼正式開始正題吧,首先我們來看看,賣一張票,總票數就減一,一般來說我們會這麼寫 package main impo...

golang 併發實踐

golang 高併發主要是依靠sync包下的api實現,首先就是waitgroup 先說說waitgroup的用途 它能夠一直等到所有的goroutine執行完成,並且阻塞主線程的執行,直到所有的goroutine執行完成。waitgroup總共有三個方法 add delta int done wa...