定義
通道是go語(yǔ)言的一種數(shù)據(jù)類(lèi)型,是goroutine之間的通信機(jī)制。
初始化
var c chan TYPE
ch := make(chan int) //無(wú)緩沖通道
ch := make(chan string ,10) //有緩沖通道
ch := make(chan<- string) //只能用于接收的通道 單向通道
ch := make(<-chan float64) //只能用于發(fā)送的通道 單項(xiàng)通道
接收元素
從一個(gè)未初始化的通道中獲取數(shù)據(jù)會(huì)永遠(yuǎn)阻塞。
從一個(gè)已關(guān)閉的通道中獲取數(shù)據(jù),如果通道中還有值可以正常獲取,如果通道中沒(méi)有值,會(huì)得到該通道類(lèi)型的零值。
從一個(gè)沒(méi)有值的通道中獲取數(shù)據(jù)會(huì)被阻塞,直到通道被寫(xiě)入數(shù)據(jù)或者關(guān)閉。
strChan := make(chan string,3)
elem := <-strChan
elem ,ok := <-strChan
發(fā)送元素
向一個(gè)未初始化的通道中寫(xiě)入數(shù)據(jù)會(huì)永遠(yuǎn)阻塞。
向一個(gè)無(wú)緩沖的通道中寫(xiě)入數(shù)據(jù)會(huì)被終阻塞,直到該通道有至少一個(gè)接收操作進(jìn)行為止,發(fā)送操作才能被喚醒。
向一個(gè)已關(guān)閉的通道寫(xiě)入數(shù)據(jù)會(huì)引起恐慌。所以不要在接收方去關(guān)閉一個(gè)通道。
向一個(gè)已滿(mǎn)的通道寫(xiě)入數(shù)據(jù)也會(huì)被阻塞,直到有接收操作完成才能被喚醒。
strChan := make(chan string,3)
strChan<-"hello"
strChan<-"world"
用法
for與channel
for的range子句可以對(duì)通道進(jìn)行讀取操作
var ch = make(chan int)
for e:= range ch{
fmt.Printf("element:%d",e)
}
for語(yǔ)句可以把通道已有的數(shù)據(jù)按順序讀出。當(dāng)通道沒(méi)有數(shù)據(jù)時(shí),for語(yǔ)句會(huì)被阻塞在range子句處。
select與channel
select語(yǔ)句是一種僅能用于通道發(fā)送和接收的語(yǔ)句。一條select語(yǔ)句執(zhí)行時(shí)會(huì)選擇其中的一個(gè)分支并執(zhí)行。
var intChan = make(chan int,10)
var strChan = make(chan string,10)
select{
case e:=<-intChan:
fmt.Printf("this case wad selected,element = %v",e)
case e:=<-strChan:
fmt.Printf("this case wad selected,element = %v",e)
default:
fmt.Println("default")
如果同時(shí)又多個(gè)case可以被觸發(fā),select會(huì)通過(guò)偽隨機(jī)的算法隨機(jī)選擇一個(gè)case并執(zhí)行。
timer與channel
定時(shí)器
time.Timer是time包提供的定時(shí)器。它可以在到達(dá)指定時(shí)間后發(fā)送一個(gè)元素到字段C中
timer := time.NewTimer(time.Second * 10)
fmt.Printf("now:%v",time.Now)
expiration := <-timer.C
fmt.Printf("now:%v",time.Now)
timer.C在10s之后才會(huì)有元素輸出,expiration定義語(yǔ)句一直被阻塞,直到10s后,才能打印第二條語(yǔ)句。
expiration := <-time.After(time.Second * 10)
與timer是等價(jià)了,簡(jiǎn)化了timer的定義。
斷續(xù)器
time.Tricker是time包提供的斷續(xù)器,它能按指定時(shí)間間隔不斷重復(fù)的發(fā)送元素到字段通道C中,當(dāng)下一次間隔時(shí)間點(diǎn)到來(lái)之時(shí),通道中還能沒(méi)被取出的元素,則當(dāng)前本次操作就會(huì)被立即取消。
var ch = make(chan int 3)
ticker := time.NewTricker(time.Second )
for _ = range ticker.C{
select {
case ch <- 1:
case ch <- 2:
case ch <- 3:
}
}
特性
并發(fā)安全
channel的數(shù)據(jù)結(jié)構(gòu)如下:
type hchan struct {
qcount uint // 數(shù)組長(zhǎng)度,即已有元素個(gè)數(shù)
dataqsiz uint // 數(shù)組容量,即可容納元素個(gè)數(shù)
buf unsafe.Pointer // 數(shù)組地址
elemsize uint16 // 元素大小
closed uint32
elemtype *_type // 元素類(lèi)型
sendx uint // 下一次寫(xiě)下標(biāo)位置
recvx uint // 下一次讀下標(biāo)位置
recvq waitq // 讀等待隊(duì)列
sendq waitq // 寫(xiě)等待隊(duì)列
lock mutex
}
lock保證了chan的多進(jìn)程之間的并發(fā)安全。
同步與異步
無(wú)緩沖通道同步
有緩沖通道異步