精品专区-精品自拍9-精品自拍三级乱伦-精品自拍视频-精品自拍视频曝光-精品自拍小视频

網站建設資訊

NEWS

網站建設資訊

go語言select go語言select源碼解析

在go語言中select關鍵字怎么用?

select 語句使得一個 goroutine 在多個通訊操作上等待。

湖南網站建設公司創新互聯,湖南網站設計制作,有大型網站制作公司豐富經驗。已為湖南近千家提供企業網站建設服務。企業網站搭建\外貿營銷網站建設要多少錢,請找那個售后服務好的湖南做網站的公司定做!

select 會阻塞,直到條件分支中的某個可以繼續執行,這時就會執行那個條件分支。當多個都準備好的時候,會隨機選擇一個。

復制代碼代碼如下:

package main

import "fmt"

func fibonacci(c, quit chan int) {

x, y := 1, 1

for {

select {

case c - x:

x, y = y, x + y

case -quit:

fmt.Println("quit")

return

}

}

}

func main() {

c := make(chan int)

quit := make(chan int)

go func() {

for i := 0; i 10; i++ {

fmt.Println(-c)

}

quit - 0

}()

fibonacci(c, quit)

}

默認選擇

當 select 中的其他條件分支都沒有準備好的時候,default 分支會被執行。

為了非阻塞的發送或者接收,可使用 default 分支:

select {

case i := -c:

// use i

default:

// receiving from c would block

}

復制代碼代碼如下:

package main

import (

"fmt"

"time"

)

func main() {

tick := time.Tick(1e8)

boom := time.After(5e8)

for {

select {

case -tick:

fmt.Println("tick.")

case -boom:

fmt.Println("BOOM!")

return

default:

fmt.Println(" .")

time.Sleep(5e7)

}

}

}

golang select 為什么要for循環

有數量不定的goroutine往channel里塞東西,然后select來接收并處理。如果所有的goroutine都完成工作,ch也接收完了,那么select就會阻塞?,F在我想要跳出死循環,大概是在for循環里設置一些東西,不知道可不可以實現,或者有類似的解決方法。

go func(){ for{ select{ case v:= 《-ch: //這里打左尖括號排版就會亂,不知道是不是網站的bug DoSomething() } } }()

go語言select的作用

Go里面提供了一個關鍵字select,通過select可以監聽channel上的數據流動。

select的用法與switch語言非常類似,由select開始一個新的選擇塊,每個選擇條件由case語句來描述。

與switch語句相比, select有比較多的限制,其中最大的一條限制就是每個case語句里必須是一個IO操作,大致的結構如下:

在一個select語句中,Go語言會按順序從頭至尾評估每一個發送和接收的語句。

如果其中的任意一語句可以繼續執行(即沒有被阻塞),那么就從那些可以執行的語句中任意選擇一條來使用。

如果沒有任意一條語句可以執行(即所有的通道都被阻塞),那么有兩種可能的情況:

如果給出了default語句,那么就會執行default語句,同時程序的執行會從select語句后的語句中恢復。

如果沒有default語句,那么select語句將被阻塞,直到至少有一個通信可以進行下去

有時候會出現goroutine阻塞的情況,那么我們如何避免整個程序進入阻塞的情況呢?我們可以利用select來設置超時,通過如下的方式實現:

select總結:

作用: 用來監聽 channel 上的數據流動方向。 讀?寫?

select實現fibonacci數列:

圖解Go中select語句的底層原理

Go 的select語句是一種僅能用于channl發送和接收消息的專用語句,此語句運行期間是阻塞的;當select中沒有case語句的時候,會阻塞當前的groutine。所以,有人也會說select是用來阻塞監聽goroutine的。

還有人說:select是Golang在語言層面提供的I/O多路復用的機制,其專門用來檢測多個channel是否準備完畢:可讀或可寫。

以上說法都正確。

我們來回顧一下是什么是 I/O多路復用 。

每來一個進程,都會建立連接,然后阻塞,直到接收到數據返回響應。

普通這種方式的缺點其實很明顯:系統需要創建和維護額外的線程或進程。因為大多數時候,大部分阻塞的線程或進程是處于等待狀態,只有少部分會接收并處理響應,而其余的都在等待。系統為此還需要多做很多額外的線程或者進程的管理工作。

為了解決圖中這些多余的線程或者進程,于是有了"I/O多路復用"

每個線程或者進程都先到圖中”裝置“中注冊,然后阻塞,然后只有一個線程在”運輸“,當注冊的線程或者進程準備好數據后,”裝置“會根據注冊的信息得到相應的數據。從始至終kernel只會使用圖中這個黃黃的線程,無需再對額外的線程或者進程進行管理,提升了效率。

select的實現經歷了多個版本的修改,當前版本為:1.11

select這個語句底層實現實際上主要由兩部分組成: case語句 和 執行函數 。

源碼地址為:/go/src/runtime/select.go

每個case語句,單獨抽象出以下結構體:

結構體可以用下圖表示:

然后執行select語句實際上就是調用 func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) 函數。

func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) 函數參數:

selectgo 返回所選scase的索引(該索引與其各自的select {recv,send,default}調用的序號位置相匹配)。此外,如果選擇的scase是接收操作(recv),則返回是否接收到值。

誰負責調用 func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) 函數呢?

在 /reflect/value.go 中有個 func rselect([]runtimeSelect) (chosen int, recvOK bool) 函數,此函數的實現在 /runtime/select.go 文件中的 func reflect_rselect(cases []runtimeSelect) (int, bool) 函數中:

那誰調用的 func rselect([]runtimeSelect) (chosen int, recvOK bool) 呢?

在 /refect/value.go 中,有一個 func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) 的函數,其調用了 rselect 函數,并將最終Go中select語句的返回值的返回。

以上這三個函數的調用棧按順序如下:

這仨函數中無論是返回值還是參數都大同小異,可以簡單粗暴的認為:函數參數傳入的是case語句,返回值返回被選中的case語句。

那誰調用了 func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) 呢?

可以簡單的認為是系統了。

來個簡單的圖:

前兩個函數 Select 和 rselect 都是做了簡單的初始化參數,調用下一個函數的操作。select真正的核心功能,是在最后一個函數 func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) 中實現的。

打亂傳入的case結構體順序

鎖住其中的所有的channel

遍歷所有的channel,查看其是否可讀或者可寫

如果其中的channel可讀或者可寫,則解鎖所有channel,并返回對應的channel數據

假如沒有channel可讀或者可寫,但是有default語句,則同上:返回default語句對應的scase并解鎖所有的channel。

假如既沒有channel可讀或者可寫,也沒有default語句,則將當前運行的groutine阻塞,并加入到當前所有channel的等待隊列中去。

然后解鎖所有channel,等待被喚醒。

此時如果有個channel可讀或者可寫ready了,則喚醒,并再次加鎖所有channel,

遍歷所有channel找到那個對應的channel和G,喚醒G,并將沒有成功的G從所有channel的等待隊列中移除。

如果對應的scase值不為空,則返回需要的值,并解鎖所有channel

如果對應的scase為空,則循環此過程。

在想想select和channel做了什么事兒,我覺得和多路復用是一回事兒


網頁名稱:go語言select go語言select源碼解析
鏈接分享:http://m.jcarcd.cn/article/hhjspj.html
主站蜘蛛池模板: 国产福利专区 | 91最新福利 | 91精品成人 | 国产又粗又猛的视频 | 福利片91 | 精品一线二线在线 | 日本最大色倩 | 国产精品青草综合久 | 日产一线 | 欧美日韩人成 | 岛国视频在线 | 91蜜桃| 欧美中文字幕第一页 | 国产精品成人自拍 | 韩剧嘟嘟网 | 国产精品有码中字 | 成人v中 | 国产伦理一区二区 | 精品自拍视频 | 国产香港日 | 国产无线乱码 | 欧美日韩一卡 | 欧美性video| 国产激情在线五月天 | 国语性爱强干bb | 午夜免费一级视频 | 国语免费 | 日本精品一区二区 | 国产人兽网址 | 国产精品区免费视频 | 无码av秘一区二区三区 | 国产黑色丝 | 国产91最新欧 | 国产自产中文综合网 | 成人年鲁鲁在线观 | 国产精品一在线观看 | 国产精品专区六区 | 日韩欧美福利在线 | 欧美亚洲日 | 国产精品玖玖 | 国产在线观看网站 |