淺析Go語(yǔ)言中Channel的各種用法
Go語(yǔ)言基礎(chǔ)四
今天我們要來(lái)學(xué)習(xí)if語(yǔ)句,也就是大家口中的判斷語(yǔ)句,我們首先來(lái)看一下if語(yǔ)句的定義
if定義
條件語(yǔ)句需要開發(fā)者通過(guò)指定一個(gè)或多個(gè)條件,并通過(guò)測(cè)試條件是否為 true 來(lái)決定是否執(zhí)行指定語(yǔ)句,并在條件為 false 的情況在執(zhí)行另外的語(yǔ)句。相信讀者看到這兒,也是云里霧里的感覺,我們?cè)趺磥?lái)表示true和false呢?
單層if語(yǔ)法格式
- 可省略條件表達(dá)式括號(hào)。
- 持初始化語(yǔ)句,可定義代碼塊局部變量。
- 代碼塊左 括號(hào)必須在條件表達(dá)式尾部。
if 布爾表達(dá)式 {
/* 在布爾表達(dá)式為 true 時(shí)執(zhí)行 */
}
這里要為讀者介紹的是,如果if后面的條件語(yǔ)句程序給出的數(shù)能夠滿足,則我們表示為true
;如果不能,則返回false
package main ? import "fmt" ? func main() { a := 3 if a > 2 { fmt.Println("true") } else { fmt.Println("false") } }
如代碼塊所示,這里我們定義了一個(gè)變量a的值為3,接下來(lái)是一個(gè)if判斷,如果該數(shù)值>2,則調(diào)用函數(shù)打印輸出true
;否則返回false
。換句話說(shuō),我們這里即是對(duì)a變量的一個(gè)判斷,至于調(diào)用函數(shù)打印輸出的內(nèi)容,由讀者自行決定
語(yǔ)法警告
在Go語(yǔ)法中,不支持三元操作符(三目運(yùn)算符) a > b ? a : b,如果讀者對(duì)三元運(yùn)算符較感興趣,可以移步至java了解三元運(yùn)算符(其本質(zhì)上也是一種if判斷形式)
package main ? import "fmt" ? func main() { /* 定義局部變量 */ var a int = 10 /* 使用 if 語(yǔ)句判斷布爾表達(dá)式 */ if a < 20 { /* 如果條件為 true 則執(zhí)行以下語(yǔ)句 */ fmt.Printf("a 小于 20\n" ) } fmt.Printf("a 的值為 : %d\n", a) }
上方是關(guān)于if判斷的一個(gè)小練習(xí),讀者自行體會(huì)即可;if
在布爾表達(dá)式為 true
時(shí),其后緊跟的語(yǔ)句塊執(zhí)行,如果為 false
則執(zhí)行 else
語(yǔ)句塊。
package main import "fmt" func main() { /* 局部變量定義 */ var a int = 100 /* 判斷布爾表達(dá)式 */ if a < 20 { /* 如果條件為 true 則執(zhí)行以下語(yǔ)句 */ fmt.Printf("a 小于 20\n" ) } else { /* 如果條件為 false 則執(zhí)行以下語(yǔ)句 */ fmt.Printf("a 不小于 20\n" ) } fmt.Printf("a 的值為 : %d\n", a) }
在Go語(yǔ)言
中,if語(yǔ)句也支持嵌套處理,即可以實(shí)現(xiàn)多重if判斷以達(dá)到程序想要的結(jié)果
多層if語(yǔ)法格式
if 布爾表達(dá)式 1 {
/* 在布爾表達(dá)式 1 為 true 時(shí)執(zhí)行 */
if 布爾表達(dá)式 2 {
/* 在布爾表達(dá)式 2 為 true 時(shí)執(zhí)行 */
}
}
package main ? import "fmt" ? func main() { /* 定義局部變量 */ var a int = 100 var b int = 200 /* 判斷條件 */ if a == 100 { /* if 條件語(yǔ)句為 true 執(zhí)行 */ if b == 200 { /* if 條件語(yǔ)句為 true 執(zhí)行 */ fmt.Printf("a 的值為 100 , b 的值為 200\n" ) } } fmt.Printf("a 值為 : %d\n", a ) fmt.Printf("b 值為 : %d\n", b ) }
如上圖所示,我們?cè)?code>if語(yǔ)句里面嵌套了另一個(gè)if語(yǔ)句,即是在默認(rèn)a == 100的情況下寫出對(duì)變量b的值的判斷,最終調(diào)用函數(shù)打印輸出a和b的值
有時(shí)候我們多個(gè)變量匹配同一個(gè)值,就會(huì)用到Switch
語(yǔ)句
Switch定義
switch
語(yǔ)句用于基于不同條件執(zhí)行不同動(dòng)作,每一個(gè) case
分支都是唯一的,從上直下逐一測(cè)試,直到匹配為止。Golang switch
分支表達(dá)式可以是任意類型,不限于常量。可省略 break
,默認(rèn)自動(dòng)終止。
Switch語(yǔ)法格式
switch var1 { case val1: ... case val2: ... default: ... }
package main import "fmt" func main() { /* 定義局部變量 */ var grade string = "B" var marks int = 90 ? switch marks { case 90: grade = "A" case 80: grade = "B" case 50,60,70 : grade = "C" default: grade = "D" } ? switch { case grade == "A" : fmt.Printf("優(yōu)秀!\n" ) case grade == "B", grade == "C" : fmt.Printf("良好\n" ) case grade == "D" : fmt.Printf("及格\n" ) case grade == "F": fmt.Printf("不及格\n" ) default: fmt.Printf("差\n" ) } fmt.Printf("你的等級(jí)是 %s\n", grade ) }
由上方代碼塊可知,我們定義了兩個(gè)局部變量grade和marks,對(duì)marks進(jìn)行Switch
判斷操作,當(dāng)case
滿足不同的值的時(shí)候,調(diào)用函數(shù)打印輸出的值也不一樣
Type Switch
switch
語(yǔ)句還可以被用于 type-switch
來(lái)判斷某個(gè) interface 變量中實(shí)際存儲(chǔ)的變量類型
Type Switch語(yǔ)法格式
switch x.(type){ case type: statement(s) case type: statement(s) /* 你可以定義任意個(gè)數(shù)的case */ default: /* 可選 */ statement(s) }
由于Type Switch
用途不是特別的多,作者在這里不作詳細(xì)描述,讀者可以去官網(wǎng)自行查詢相關(guān)文檔進(jìn)行學(xué)習(xí)
Select定義
select
語(yǔ)句類似于switch
語(yǔ)句,但是select
會(huì)隨機(jī)執(zhí)行一個(gè)可運(yùn)行的case
。如果沒(méi)有case
可運(yùn)行,它將阻塞,直到有case
可運(yùn)行。select
是Go
中的一個(gè)控制結(jié)構(gòu),類似于用于通信的switch
語(yǔ)句。每個(gè)case
必須是一個(gè)通信操作,要么是發(fā)送要么是接收。select
隨機(jī)執(zhí)行一個(gè)可運(yùn)行的case
。如果沒(méi)有case
可運(yùn)行,它將阻塞,直到有case
可運(yùn)行。一個(gè)默認(rèn)的子句應(yīng)該總是可運(yùn)行的。
Select語(yǔ)法格式
select { case communication clause : statement(s); case communication clause : statement(s); /* 你可以定義任意數(shù)量的 case */ default : /* 可選 */ statement(s); }
Select語(yǔ)句注意事項(xiàng)
- 每個(gè)
case
都必須是一個(gè)通信 - 所有
channel
表達(dá)式都會(huì)被求值 - 所有被發(fā)送的表達(dá)式都會(huì)被求值
- 如果任意某個(gè)通信可以進(jìn)行,它就執(zhí)行;其他被忽略。
- 如果有多個(gè)
case
都可以運(yùn)行,Select會(huì)隨機(jī)公平地選出一個(gè)執(zhí)行。其他不會(huì)執(zhí)行。 - 如果有
default
子句,則執(zhí)行該語(yǔ)句。 - 如果沒(méi)有
default
字句,select
將阻塞,直到某個(gè)通信可以運(yùn)行;Go
不會(huì)重新對(duì)channel
值重新進(jìn)行求值。
package main ? import "fmt" ? func main() { var c1, c2, c3 chan int //通道機(jī)制 var i1, i2 int select { case i1 = <-c1: fmt.Printf("received ", i1, " from c1\n") case c2 <- i2: fmt.Printf("sent ", i2, " to c2\n") case i3, ok := (<-c3): // same as: i3, ok := <-c3 if ok { fmt.Printf("received ", i3, " from c3\n") } else { fmt.Printf("c3 is closed\n") } default: fmt.Printf("no communication\n") } }
根據(jù)上方代碼所示,定義了c1、c2、c3
三個(gè)變量,并且使用chan
通道。關(guān)于寫法的解釋:一個(gè)可以發(fā)送 int
類型數(shù)據(jù)的 channel
一般寫為 chan int
,根據(jù)上方的語(yǔ)法規(guī)則:如果有default
子句,則執(zhí)行該語(yǔ)句,故上方代碼塊執(zhí)行代碼為:no communication
Select用法補(bǔ)充
- 我們可以使用
select
來(lái)監(jiān)聽channel
的數(shù)據(jù)流動(dòng) select
的用法與switch
語(yǔ)法非常類似,由select
開始的一個(gè)新的選擇塊,每個(gè)選擇條件由case
語(yǔ)句來(lái)描述switch
語(yǔ)句可以選擇任何使用相等比較的條件相比,select
由比較多的限制,其中最大的一條限制就是每個(gè)case
語(yǔ)句里必須是一個(gè)IO操作
- 如果每個(gè)
case
都未讀取到,則Go語(yǔ)言
會(huì)自動(dòng)讀取default
語(yǔ)句所描述的東西,在正常情況下,每個(gè)select
程序都會(huì)有一個(gè)輸出語(yǔ)句 - 如果既沒(méi)有
case
語(yǔ)句滿足,也不存在default
語(yǔ)句,則程序進(jìn)入阻塞狀態(tài),系統(tǒng)會(huì)發(fā)出警告,直至疏通
超時(shí)判斷
var resChan = make(chan int) // do request func test() { select { case data := <-resChan: doData(data) case <-time.After(time.Second * 3): fmt.Println("request time out") } } ? func doData(data int) { //... }
根據(jù)上方代碼塊可知,我們定義了一個(gè)select
語(yǔ)句,在第一條case
里面,我們將resChan
傳給data
,如果在傳輸?shù)倪^(guò)程中時(shí)長(zhǎng)超過(guò)3s,則會(huì)執(zhí)行第二條case
語(yǔ)句
退出
var shouldQuit=make(chan struct{}) fun main(){ { //loop } //...out of the loop select { case <-c.shouldQuit: cleanUp() return default: } //... } ? //在另外一個(gè)協(xié)程中,如果運(yùn)行遇到非法操作或不可處理的錯(cuò)誤,就向shouldQuit發(fā)送數(shù)據(jù)通知程序停止運(yùn)行 close(shouldQuit)
我們定義一個(gè)var類型的shouldQuit
變量用于結(jié)構(gòu)體的通道,首先我們開啟一個(gè)select循環(huán),在case
里面調(diào)用通道方法,并且返回所對(duì)應(yīng)的值;如果不滿足,則返回default的值。同時(shí)我們?cè)?strong>另外一個(gè)協(xié)程中,如果我們遇到了非法操作或不可處理的錯(cuò)誤,就向shouldQuit
發(fā)送數(shù)據(jù)通知程序停止運(yùn)行
判斷Channel狀態(tài)
ch := make (chan int, 5) //... data:=0 select { case ch <- data: default: }
有時(shí)候我們不喜歡緩存變慢,這樣不利于我們?nèi)メ尫刨Y源,因此我們可以用一個(gè)簡(jiǎn)單的判斷方法去進(jìn)行判斷:首先我們開啟一個(gè)int類型,長(zhǎng)度為5的通道,在通道里面我們開啟一個(gè)select
循環(huán),如果data通道的值能被ch所接收,則執(zhí)行該條語(yǔ)句,否則我們可對(duì)default語(yǔ)句
進(jìn)行拋棄data等處理操作
到此這篇關(guān)于淺析Go語(yǔ)言中Channel的各種用法的文章就介紹到這了,更多相關(guān)Go語(yǔ)言Channel用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決goland新建項(xiàng)目文件名為紅色的問(wèn)題
這篇文章主要介紹了解決goland新建項(xiàng)目文件名為紅色的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12用go語(yǔ)言實(shí)現(xiàn)WebAssembly數(shù)據(jù)加密的示例講解
在Web開發(fā)中,有時(shí)候?yàn)榱颂嵘踩孕枰獙?duì)數(shù)據(jù)進(jìn)行加密,由于js代碼相對(duì)比較易讀,直接在js中做加密安全性較低,而WebAssembly代碼不如js易讀,本文提供一個(gè)用go語(yǔ)言實(shí)現(xiàn)的WebAssembly數(shù)據(jù)加密示例,需要的朋友可以參考下2024-03-03詳解Go語(yǔ)言運(yùn)用廣度優(yōu)先搜索走迷宮
廣度優(yōu)先搜索是從圖中的某一頂點(diǎn)出發(fā),遍歷每一個(gè)頂點(diǎn)時(shí),依次遍歷其所有的鄰接點(diǎn),再?gòu)倪@些鄰接點(diǎn)出發(fā),依次訪問(wèn)它們的鄰接點(diǎn),直到圖中所有被訪問(wèn)過(guò)的頂點(diǎn)的鄰接點(diǎn)都被訪問(wèn)到。然后查看圖中是否存在尚未被訪問(wèn)的頂點(diǎn),若有,則以該頂點(diǎn)為起始點(diǎn),重復(fù)上述遍歷的過(guò)程2021-06-06

詳解golang 定時(shí)任務(wù)time.Sleep和time.Tick實(shí)現(xiàn)結(jié)果比較