您好,登錄后才能下訂單哦!
本文主要給大家介紹了關(guān)于Golang中switch和select用法的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面來一起看看詳細(xì)的介紹:
一、switch語句
switch語句提供了一個(gè)多分支條件執(zhí)行的方法。每一個(gè)case可以攜帶一個(gè)表達(dá)式或一個(gè)類型說明符。前者又可被簡稱為case表達(dá)式。因此,Go語言的switch語句又分為表達(dá)式switch語句和類型switch語句。
1、表達(dá)式switch語句
var name string ... switch name { case "Golang": fmt.Println("Golang") case "Rust": fmt.Println("Rust") default: fmt.Println("PHP是世界上最好的語言") }
Go會依照從上至下的順序?qū)γ恳粭lcase語句中case表達(dá)式進(jìn)行求值,只要被發(fā)現(xiàn)其表達(dá)式與switch表達(dá)式的結(jié)果相同,該case語句就會被選中。其余的case語句會被忽略。 與if相同,switch語句還可以包含初始化字句,且其出現(xiàn)位置和寫法如出一轍:
names := []string{"Golang","java","PHP"} switch name:=names[0];name { case "Golang": fmt.Println("Golang") ... default: fmt.Println("Unknown") }
2、類型switch語句
類型switch語句與一般形式有兩點(diǎn)差別。第一點(diǎn),緊隨case關(guān)鍵字的不是表達(dá)式,而是類型說明符。類型說明符由若干個(gè)類型字面量組成,且多個(gè)類型字面量之間由英文逗號分隔。第二點(diǎn),它的switch表達(dá)式是非常特殊的。這種特殊的表達(dá)式也起到了類型斷言的作用,但其表現(xiàn)形式很特殊,如:v.(type)
, 其中v必須代表一個(gè)接口類型的值。該類表達(dá)式只能出現(xiàn)在類型switch語句中,且只能充當(dāng)switch表達(dá)式。一個(gè)類型switch語句的示例如下:
v := 11 switch i := interface{}(v).(type) { case int, int8, int16, int32, int64: fmt.Println("A signed integer:%d. The type is %T. \n", v, i) case uint, uint8, uint16, uint32, uint64: fmt.Println("A unsigned integer: %d. The type is %T. \n", v, i) default: fmt.Println("Unknown!") }
我們這里把switch表達(dá)式的結(jié)果賦給了一個(gè)變量。如此以來,我們就可以在該switch語句中使用這個(gè)結(jié)果了。這段代碼被執(zhí)行后,輸出:"A signed integer:11. The type is int.
"
最后說一下fallthrough。它既是一個(gè)關(guān)鍵字,又可以代表一條語句。fallthrough語句可被包含在表達(dá)式switch語句中的case語句中。它的作用是使控制權(quán)流轉(zhuǎn)到下一個(gè)case。不過要注意fallthrough語句僅能作為case語句中的最后一條語句出現(xiàn)。并且,包含它的case語句不是其所屬switch語句的最后一條case語句。
二、select語句
golang 的 select 的功能和 select, poll, epoll 相似, 就是監(jiān)聽 IO 操作,當(dāng) IO 操作發(fā)生時(shí),觸發(fā)相應(yīng)的動作。
示例:
ch2 := make (chan int, 1) ch3 := make (chan int, 1) ... select { case <-ch2: fmt.Println("ch2 pop one element") case <-ch3: fmt.Println("ch3 pop one element") }
注意到 select 的代碼形式和 switch 非常相似, 不過 select 的 case 里的操作語句只能是【IO 操作】 。
此示例里面 select 會一直等待等到某個(gè) case 語句完成, 也就是等到成功從 ch2 或者 ch3 中讀到數(shù)據(jù)。 則 select 語句結(jié)束。
break語句也可以被包含在select語句中的case語句中。它的作用是立即結(jié)束當(dāng)前的select語句的執(zhí)行。不論其所屬的case語句中是否還有未被執(zhí)行的語句。
【使用 select 實(shí)現(xiàn) timeout 機(jī)制】
如下:
timeout := make(chan bool, 1) go func() { time.Sleep(time.Second * 10) timeout <- true }() select { case <-pssScanResponseChan: case <-timeout: fmt.PrintIn("timeout!") }
當(dāng)超時(shí)時(shí)間到的時(shí)候,case2 會操作成功。 所以 select 語句則會退出。 而不是一直阻塞在 ch 的讀取操作上。 從而實(shí)現(xiàn)了對 ch 讀取操作的超時(shí)設(shè)置。
下面這個(gè)更有意思一點(diǎn)。
當(dāng) select 語句帶有 default 的時(shí)候:
ch2 := make (chan int, 1) ch3 := make (chan int, 1) select { case <-ch2: fmt.Println("ch2 pop one element") case <-ch3: fmt.Println("ch3 pop one element") default: fmt.Println("default") }
此時(shí)因?yàn)?ch2 和 ch3 都為空,所以 case1 和 case2 都不會讀取成功。 則 select 執(zhí)行 default 語句。
就是因?yàn)檫@個(gè) default 特性, 我們可以使用 select 語句來檢測 chan 是否已經(jīng)滿了。
如下:
ch := make (chan int, 1) ch <- 1 select { case ch <- 2: default: fmt.Println("channel is full !") }
因?yàn)?ch 插入 1 的時(shí)候已經(jīng)滿了, 當(dāng) ch 要插入 2 的時(shí)候,發(fā)現(xiàn) ch 已經(jīng)滿了(case1 阻塞?。?則 select 執(zhí)行 default 語句。 這樣就可以實(shí)現(xiàn)對 channel 是否已滿的檢測, 而不是一直等待。
比如我們有一個(gè)服務(wù), 當(dāng)請求進(jìn)來的時(shí)候我們會生成一個(gè) job 扔進(jìn) channel, 由其他協(xié)程從 channel 中獲取 job 去執(zhí)行。 但是我們希望當(dāng) channel 瞞了的時(shí)候, 將該 job 拋棄并回復(fù) 【服務(wù)繁忙,請稍微再試。】 就可以用 select 實(shí)現(xiàn)該需求。
此外,利用default特性,我們可以使用select語句將chan清空,如下:
flag := false for { select { case <-pssScanResponseChan: continue default: flag = true } if true == flag { break } }
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。