Go?select使用與底層原理講解
1. select的使用
select 是 Go 提供的 IO 多路復(fù)用機(jī)制,可以用多個 case 同時監(jiān)聽多個 channl 的讀寫狀態(tài):
- case: 可以監(jiān)聽 channl 的讀寫信號
- default:聲明默認(rèn)操作,有該字段的 select 不會阻塞
select { case chan <-: // TODO case <- chan: // TODO default: // TODO }
2. 底層原理
- 每一個 case 對應(yīng)的 channl 都會被封裝到一個結(jié)構(gòu)體中;
- 當(dāng)?shù)谝淮螆?zhí)行到 select 時,會鎖住所有的 channl 并且,打亂 case 結(jié)構(gòu)體的順序;
- 按照打亂的順序遍歷,如果有就緒的信號,就直接走對應(yīng) case 的代碼段,之后跳出 select;
- 如果沒有就緒的代碼段,但是有 default 字段,那就走 default 的代碼段,之后跳出 select;
- 如果沒有 default,那就將當(dāng)前 goroutine 加入所有 channl 的對應(yīng)等待隊列;
- 當(dāng)某一個等待隊列就緒時,再次鎖住所有的 channl,遍歷一遍,將所有等待隊列中的 goroutine 取出,之后執(zhí)行就緒的代碼段,跳出select。
3. 數(shù)據(jù)結(jié)構(gòu)
每一個 case 對應(yīng)的數(shù)據(jù)結(jié)構(gòu)如下:
type scase struct { c *hchan // chan elem unsafe.Pointer // 讀或者寫的緩沖區(qū)地址 kind uint16 //case語句的類型,是default、傳值寫數(shù)據(jù)(channel <-) 還是 取值讀數(shù)據(jù)(<- channel) pc uintptr // race pc (for race detector / msan) releasetime int64 }
4. 幾種常見 case
學(xué)習(xí)了 select 的使用與原理,我們就能更輕松地分辨不同情況下的輸出情況了。
case 1
package main import ( "fmt" "time" ) func main() { chan1 := make(chan int) chan2 := make(chan int) go func() { chan1 <- 1 time.Sleep(5 * time.Second) }() go func() { chan2 <- 1 time.Sleep(5 * time.Second) }() select { case <- chan1: fmt.Println("chan1") case <- chan2: fmt.Println("chan2") default: fmt.Println("default") } }
三種輸出都有可能。
case2
package main import ( "fmt" "time" ) func main() { chan1 := make(chan int) chan2 := make(chan int) select { case <- chan1: fmt.Println("chan1") case <- chan2: fmt.Println("chan2") } fmt.Println("main exit.") }
上述程序會一直阻塞。
case3
package main import ( "fmt" ) func main() { chan1 := make(chan int) chan2 := make(chan int) go func() { close(chan1) }() go func() { close(chan2) }() select { case <- chan1: fmt.Println("chan1") case <- chan2: fmt.Println("chan2") } fmt.Println("main exit.") }
隨機(jī)執(zhí)行1或者2.
case4
package main func main() { select { } }
對于空的 select 語句,程序會被阻塞,確切的說是當(dāng)前協(xié)程被阻塞,同時 Go 自帶死鎖檢測機(jī)制,當(dāng)發(fā)現(xiàn)當(dāng)前協(xié)程再也沒有機(jī)會被喚醒時,則會發(fā)生 panic。所以上述程序會 panic。
到此這篇關(guān)于Go select使用與底層原理講解的文章就介紹到這了,更多相關(guān)Go select使用 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- go語言中如何使用select的實(shí)現(xiàn)示例
- go select編譯期的優(yōu)化處理邏輯使用場景分析
- Go語言使用select{}阻塞main函數(shù)介紹
- matplotlib之多邊形選區(qū)(PolygonSelector)的使用
- Golang的select多路復(fù)用及channel使用操作
- 深入了解Go的interface{}底層原理實(shí)現(xiàn)
- Go語言CSP并發(fā)模型goroutine及channel底層實(shí)現(xiàn)原理
- Go語言中的并發(fā)goroutine底層原理
- Golang 語言map底層實(shí)現(xiàn)原理解析
相關(guān)文章
Go 語言中的 http.FileSystem詳細(xì)解析
在本文中,我們深入探討了 Go 語言中的 http.FileSystem 接口,并介紹了它的基本原理、使用方法以及實(shí)際應(yīng)用場景,感興趣的朋友跟隨小編一起看看吧2024-03-03GoFrame框架數(shù)據(jù)校驗(yàn)之校驗(yàn)對象校驗(yàn)結(jié)構(gòu)體
這篇文章主要為大家介紹了GoFrame框架數(shù)據(jù)校驗(yàn)之校驗(yàn)對象校驗(yàn)結(jié)構(gòu)體示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06go語言實(shí)現(xiàn)銀行卡號Luhn校驗(yàn)
這篇文章主要為大家介紹了go語言Luhn校驗(yàn)測試銀行卡號碼的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05