Go?select使用與底層原理講解
1. select的使用
select 是 Go 提供的 IO 多路復(fù)用機(jī)制,可以用多個(gè) case 同時(shí)監(jiān)聽(tīng)多個(gè) channl 的讀寫(xiě)狀態(tài):
- case: 可以監(jiān)聽(tīng) channl 的讀寫(xiě)信號(hào)
- default:聲明默認(rèn)操作,有該字段的 select 不會(huì)阻塞
select {
case chan <-:
// TODO
case <- chan:
// TODO
default:
// TODO
}2. 底層原理
- 每一個(gè) case 對(duì)應(yīng)的 channl 都會(huì)被封裝到一個(gè)結(jié)構(gòu)體中;
- 當(dāng)?shù)谝淮螆?zhí)行到 select 時(shí),會(huì)鎖住所有的 channl 并且,打亂 case 結(jié)構(gòu)體的順序;
- 按照打亂的順序遍歷,如果有就緒的信號(hào),就直接走對(duì)應(yīng) case 的代碼段,之后跳出 select;
- 如果沒(méi)有就緒的代碼段,但是有 default 字段,那就走 default 的代碼段,之后跳出 select;
- 如果沒(méi)有 default,那就將當(dāng)前 goroutine 加入所有 channl 的對(duì)應(yīng)等待隊(duì)列;
- 當(dāng)某一個(gè)等待隊(duì)列就緒時(shí),再次鎖住所有的 channl,遍歷一遍,將所有等待隊(duì)列中的 goroutine 取出,之后執(zhí)行就緒的代碼段,跳出select。
3. 數(shù)據(jù)結(jié)構(gòu)
每一個(gè) case 對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)如下:
type scase struct {
c *hchan // chan
elem unsafe.Pointer // 讀或者寫(xiě)的緩沖區(qū)地址
kind uint16 //case語(yǔ)句的類(lèi)型,是default、傳值寫(xiě)數(shù)據(jù)(channel <-) 還是 取值讀數(shù)據(jù)(<- channel)
pc uintptr // race pc (for race detector / msan)
releasetime int64
}4. 幾種常見(jiàn) 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.")
}上述程序會(huì)一直阻塞。
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 {
}
}對(duì)于空的 select 語(yǔ)句,程序會(huì)被阻塞,確切的說(shuō)是當(dāng)前協(xié)程被阻塞,同時(shí) Go 自帶死鎖檢測(cè)機(jī)制,當(dāng)發(fā)現(xiàn)當(dāng)前協(xié)程再也沒(méi)有機(jī)會(huì)被喚醒時(shí),則會(huì)發(fā)生 panic。所以上述程序會(huì) panic。
到此這篇關(guān)于Go select使用與底層原理講解的文章就介紹到這了,更多相關(guān)Go select使用 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- go語(yǔ)言中如何使用select的實(shí)現(xiàn)示例
- go select編譯期的優(yōu)化處理邏輯使用場(chǎng)景分析
- Go語(yǔ)言使用select{}阻塞main函數(shù)介紹
- matplotlib之多邊形選區(qū)(PolygonSelector)的使用
- Golang的select多路復(fù)用及channel使用操作
- 深入了解Go的interface{}底層原理實(shí)現(xiàn)
- Go語(yǔ)言CSP并發(fā)模型goroutine及channel底層實(shí)現(xiàn)原理
- Go語(yǔ)言中的并發(fā)goroutine底層原理
- Golang 語(yǔ)言map底層實(shí)現(xiàn)原理解析
相關(guān)文章
Go 語(yǔ)言中的 http.FileSystem詳細(xì)解析
在本文中,我們深入探討了 Go 語(yǔ)言中的 http.FileSystem 接口,并介紹了它的基本原理、使用方法以及實(shí)際應(yīng)用場(chǎng)景,感興趣的朋友跟隨小編一起看看吧2024-03-03
GoFrame框架數(shù)據(jù)校驗(yàn)之校驗(yàn)對(duì)象校驗(yàn)結(jié)構(gòu)體
這篇文章主要為大家介紹了GoFrame框架數(shù)據(jù)校驗(yàn)之校驗(yàn)對(duì)象校驗(yàn)結(jié)構(gòu)體示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
我為什么喜歡Go語(yǔ)言(簡(jiǎn)潔的Go語(yǔ)言)
從2000年至今,也寫(xiě)了11年代碼了,期間用過(guò)VB、Delphi、C#、C++、Ruby、Python,一直在尋找一門(mén)符合自己心意和理念的語(yǔ)言。我很在意寫(xiě)代碼時(shí)的手感和執(zhí)行的效率,所以在Go出現(xiàn)之前一直沒(méi)有找到2014-10-10
go語(yǔ)言實(shí)現(xiàn)銀行卡號(hào)Luhn校驗(yàn)
這篇文章主要為大家介紹了go語(yǔ)言L(fǎng)uhn校驗(yàn)測(cè)試銀行卡號(hào)碼的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Go 語(yǔ)言結(jié)構(gòu)實(shí)例分析
在本篇文章里小編給大家整理的是一篇關(guān)于Go 語(yǔ)言結(jié)構(gòu)實(shí)例分析的相關(guān)知識(shí)點(diǎn),有興趣的朋友們可以學(xué)習(xí)下。2021-07-07
Go語(yǔ)言獲取本機(jī)邏輯CPU數(shù)量的方法
這篇文章主要介紹了Go語(yǔ)言獲取本機(jī)邏輯CPU數(shù)量的方法,實(shí)例分析了runtime庫(kù)的操作技巧,需要的朋友可以參考下2015-03-03
golang?對(duì)象深拷貝的常見(jiàn)方式及性能
這篇文章主要介紹了golang?對(duì)象深拷貝的常見(jiàn)方式及性能,Go語(yǔ)言中所有賦值操作都是值傳遞,如果結(jié)構(gòu)中不含指針,則直接賦值就是深度拷貝,文章圍繞主題展開(kāi)更多相關(guān)資料,需要的小伙伴可以參考一下2022-06-06
關(guān)于golang類(lèi)型推斷和變量重聲明詳解
在Go語(yǔ)言中,類(lèi)型推斷可以根據(jù)變量的初始化值自動(dòng)推斷出變量的類(lèi)型,而不需要顯式地聲明變量類(lèi)型,變量重聲明可以在同一作用域內(nèi)重復(fù)聲明一個(gè)變量,只要其中至少一個(gè)是新的變量,本就簡(jiǎn)單的給大家介紹一下golang類(lèi)型推斷和變量重聲明,需要的朋友可以參考下2023-08-08
go語(yǔ)言題解LeetCode674最長(zhǎng)連續(xù)遞增序列
這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode674最長(zhǎng)連續(xù)遞增序列示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12

