欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺析Go語言如何在select語句中實現(xiàn)優(yōu)先級

 更新時間:2024年03月18日 10:59:03   作者:神武  
這篇文章主要為大家詳細介紹了Go語言如何在select語句中實現(xiàn)優(yōu)先級,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

Go 語言中的 select語句用于監(jiān)控并選擇一組case語句執(zhí)行相應(yīng)的代碼。它看起來類似于switch語句,但是select語句中所有case中的表達式都必須是channel的發(fā)送或接收操作。一個典型的select使用示例如下

select {
case <-ch1:
	fmt.Println("liwenzhou.com")
case ch2 <- 1:
	fmt.Println("q1mi")
}

Go 語言中的 select 關(guān)鍵字也能夠讓當(dāng)前 goroutine 同時等待ch1 的可讀和ch2的可寫,在ch1ch2狀態(tài)改變之前,select 會一直阻塞下去,直到其中的一個 channel 轉(zhuǎn)為就緒狀態(tài)時執(zhí)行對應(yīng)case分支的代碼。如果多個channel同時就緒的話則隨機選擇一個case執(zhí)行。

除了上面展示的典型示例外,接下來我們逐一介紹一些select的特殊示例。

空select

select指的是內(nèi)部不包含任何case,例如:

select{
  
}

空的 select 語句會直接阻塞當(dāng)前的goroutine,使得該goroutine進入無法被喚醒的永久休眠狀態(tài)。

只有一個case

如果select中只包含一個case,那么該select就變成了一個阻塞的channel讀/寫操作。

select {
case <-ch1:
	fmt.Println("liwenzhou.com")
}

上面的代碼,當(dāng)ch1可讀時會執(zhí)行打印操作,否則就會阻塞。

有default語句

如果select中還可以包含default語句,用于當(dāng)其他case都不滿足時執(zhí)行一些默認操作。

select {
case <-ch1:
	fmt.Println("liwenzhou.com")
default:
	time.Sleep(time.Second)
}

上面的代碼,當(dāng)ch1可讀時會執(zhí)行打印操作,否則就執(zhí)行default語句中的代碼,這里就相當(dāng)于做了一個非阻塞的channel讀取操作。

總結(jié)

  • select 不存在任何的 case:永久阻塞當(dāng)前 goroutine
  • select 只存在一個 case:阻塞的發(fā)送/接收
  • select 存在多個 case:隨機選擇一個滿足條件的case執(zhí)行
  • select 存在 default,其他case都不滿足時:執(zhí)行default語句中的代碼

如何在select中實現(xiàn)優(yōu)先級

已知,當(dāng)select 存在多個 case時會隨機選擇一個滿足條件的case執(zhí)行。

現(xiàn)在我們有一個需求:我們有一個函數(shù)會持續(xù)不間斷地從ch1ch2中分別接收任務(wù)1和任務(wù)2, 如何確保當(dāng)ch1ch2同時達到就緒狀態(tài)時,優(yōu)先執(zhí)行任務(wù)1,在沒有任務(wù)1的時候再去執(zhí)行任務(wù)2呢?

高級Go語言程序員小明撓了撓頭寫出了如下函數(shù):

func worker(ch1, ch2 <-chan int, stopCh chan struct{}) {

	for {
		select {
		case <-stopCh:
			return
		case job1 := <-ch1:
			fmt.Println(job1)
		default:
			select {
			case job2 := <-ch2:
				fmt.Println(job2)
			default:
			}
		}
	}
}

上面的代碼通過嵌套兩個select實現(xiàn)了"優(yōu)先級",看起來是滿足題目要求的。但是這代碼有點問題,如果ch1ch2都沒有達到就緒狀態(tài)的話,整個程序不會阻塞而是進入了死循環(huán)。

怎么辦呢?

小明又撓了撓頭,又寫下了另一個解決方案:

func worker2(ch1, ch2 <-chan int, stopCh chan struct{}) {
	for {
		select {
		case <-stopCh:
			return
		case job1 := <-ch1:
			fmt.Println(job1)
		case job2 := <-ch2:
		priority:
			for {
				select {
				case job1 := <-ch1:
					fmt.Println(job1)
				default:
					break priority
				}
			}
			fmt.Println(job2)
		}
	}
}

這一次,小明不僅使用了嵌套的select,還組合使用了for循環(huán)和LABEL來實現(xiàn)題目的要求。上面的代碼在外層select選中執(zhí)行job2 := <-ch2時,進入到內(nèi)層select循環(huán)繼續(xù)嘗試執(zhí)行job1 := <-ch1,當(dāng)ch1就緒時就會一直執(zhí)行,否則跳出內(nèi)層select

實際應(yīng)用場景

上面的需求雖然是我編的,但是關(guān)于在select中實現(xiàn)優(yōu)先級在實際生產(chǎn)中是有實際應(yīng)用場景的,例如K8s的controller中就有關(guān)于上面這個技巧的實際使用示例,這里在關(guān)于select中實現(xiàn)優(yōu)先級相關(guān)代碼的關(guān)鍵處都已添加了注釋,具體邏輯這里就不展開細說了。

// kubernetes/pkg/controller/nodelifecycle/scheduler/taint_manager.go 
func (tc *NoExecuteTaintManager) worker(worker int, done func(), stopCh <-chan struct{}) {
	defer done()

	// 當(dāng)處理具體事件的時候,我們會希望 Node 的更新操作優(yōu)先于 Pod 的更新
	// 因為 NodeUpdates 與 NoExecuteTaintManager無關(guān)應(yīng)該盡快處理
	// -- 我們不希望用戶(或系統(tǒng))等到PodUpdate隊列被耗盡后,才開始從受污染的Node中清除pod。
	for {
		select {
		case <-stopCh:
			return
		case nodeUpdate := <-tc.nodeUpdateChannels[worker]:
			tc.handleNodeUpdate(nodeUpdate)
			tc.nodeUpdateQueue.Done(nodeUpdate)
		case podUpdate := <-tc.podUpdateChannels[worker]:
			// 如果我們發(fā)現(xiàn)了一個 Pod 需要更新,我么你需要先清空 Node 隊列.
		priority:
			for {
				select {
				case nodeUpdate := <-tc.nodeUpdateChannels[worker]:
					tc.handleNodeUpdate(nodeUpdate)
					tc.nodeUpdateQueue.Done(nodeUpdate)
				default:
					break priority
				}
			}
			// 在 Node 隊列清空后我們再處理 podUpdate.
			tc.handlePodUpdate(podUpdate)
			tc.podUpdateQueue.Done(podUpdate)
		}
	}
}

到此這篇關(guān)于淺析Go語言如何在select語句中實現(xiàn)優(yōu)先級的文章就介紹到這了,更多相關(guān)Go select優(yōu)先級內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • B站新一代 golang規(guī)則引擎gengine基礎(chǔ)語法

    B站新一代 golang規(guī)則引擎gengine基礎(chǔ)語法

    這篇文章主要為大家介紹了B站新一代 golang規(guī)則引擎gengine基礎(chǔ)語法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • golang高并發(fā)限流操作 ping / telnet

    golang高并發(fā)限流操作 ping / telnet

    這篇文章主要介紹了golang高并發(fā)限流操作 ping / telnet,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang實現(xiàn)快速求冪的方法詳解

    Golang實現(xiàn)快速求冪的方法詳解

    這篇文章主要為大家詳細介紹了如何利用Golang實現(xiàn)快速求冪,文中的示例代碼講解詳細,對我們學(xué)習(xí)或工作有一定參考價值,需要的可以參考一下
    2022-06-06
  • golang copy函數(shù)使用的坑

    golang copy函數(shù)使用的坑

    本文主要介紹了golang copy函數(shù)使用的坑,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Go語言下載網(wǎng)絡(luò)圖片或文件的方法示例

    Go語言下載網(wǎng)絡(luò)圖片或文件的方法示例

    這篇文章主要介紹了Go語言下載網(wǎng)絡(luò)圖片或文件的方法示例,文中通過示例代碼介紹的非常詳細,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • golang hack插件開發(fā)動態(tài)鏈接庫實例探究

    golang hack插件開發(fā)動態(tài)鏈接庫實例探究

    這篇文章主要為大家介紹了golang hack插件開發(fā)動態(tài)鏈接庫實例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • go?打包運行文件在windows,liunx運行

    go?打包運行文件在windows,liunx運行

    這篇文章主要介紹了go?打包運行文件在windows,liunx運行的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • Goland和IDEA換行符的設(shè)置方式

    Goland和IDEA換行符的設(shè)置方式

    這篇文章主要介紹了Goland和IDEA換行符的設(shè)置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Go 實現(xiàn)英尺和米的簡單單位換算方式

    Go 實現(xiàn)英尺和米的簡單單位換算方式

    這篇文章主要介紹了Go 實現(xiàn)英尺和米的簡單單位換算方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go語言讀取文本文件的三種方式總結(jié)

    Go語言讀取文本文件的三種方式總結(jié)

    工作中時不時需要讀取文本,文本文件是最常見的文件類型。本文將利用Go語言從逐行、逐個單詞和逐個字符三個方法讀取文件,感興趣的可以了解一下
    2023-01-01

最新評論