iT邦幫忙

2024 iThome 鐵人賽

DAY 16
0
Software Development

可以Go一輩子嗎?系列 第 16

Go語言中的Channel介紹與使用

  • 分享至 

  • xImage
  •  

Day16. Go語言中的Channel介紹與使用

今天來講Channel是Go語言中的一個重要概念,它是用來在不同的goroutine之間傳遞數據的一種方式(類似於Unix中的管道),這使得Go語言在處理併發任務時非常優雅和高效

前言

在Go語言中,Channel是一個引用類型,需要使用make()函數來初始化。否則沒有初始化的Channel是nil。Channel通道中的數據是按照先進先出(FIFO)的原則進行傳遞的。
當對Channel進行資料讀取或寫入時,會阻塞當前的goroutine,然後把執行環境交給另一個 goroutine,直到 channel 有進有出後才會回到該 goroutine 作用環境。以確保資料的正確性。且因此我們可以不用額外的同步機制來保證資料的正確性。

Channel的使用

宣告Channel

// read only channel
var chronly <-chan int

// write only channel
var chwrite chan<- int

// read and write channel
var ch chan int

// make a channel
ch := make(chan int)
chBuffered := make(chan int, 10) // buffered channel with capacity 10

可以注意到,對於只能寫入或讀取的Channel宣告,我們可以透過箭頭指向哪裡來分辨是寫入還是讀取的Channel,從chan指到變數表示這是一個唯讀Channel,從類別指到chan表示這是一個唯寫Channel
而對於Buffer Channel(在make時有指定容量),當Channel滿了時,寫入操作會被阻塞,直到有空間可以寫入,當Channel為空時,讀取操作會被阻塞,直到有數據可以讀取,因此可以用來確保goroutine完成後再繼續執行
如果你在同一個goroutine中寫入超過Channel的容量,會導致deadlock

Channel的使用

我們一樣可以透過箭頭來指定寫入或讀取的Channel,簡單來說, 從Channel指出來的箭頭表示讀取,指向Channel的箭頭表示寫入

ch := make(chan int)
go func() {
    ch <- 1 // write to channel
}()

go func() {
    fmt.Println(<-ch) // read from channel
}()

func readFromChannel(ch <-chan int) {
    fmt.Println(<-ch) // read from channel
}

如果確定沒有要繼續寫入資料到Channel,可以使用close(ch)函數來關閉Channel,這樣可以避免deadlock。關閉後可以繼續讀取Channel中的資料,但是無法再寫入資料到Channel

ch := make(chan int)
go func() {
    ch <- 1 // write to channel
    close(ch)
}()

檢查Channel是否關閉

可以使用v, ok := <-ch來檢查Channel是否已經關閉,如果Channel已經關閉時, ok會返回false

ch := make(chan int)
go func() {
    ch <- 1 // write to channel
    close(ch)
}()

for {
    v, ok := <-ch
    if !ok {
        break
    }
    fmt.Println(v)
}

你甚至可以使用range來輸出Channel中的所有資料,因為在range中的Channel會自動檢查Channel是否已經關閉,並且在Channel關閉後自動退出迴圈

ch := make(chan int)
go func() {
    ch <- 1 // write to channel
    ch <- 2 // write to channel
    close(ch)
}()

for v := range ch {
    fmt.Println(v)
}

那麼今天的文章就到這告一段落,如果我的文章有任何地方有錯誤請在留言區反應
明天將會介紹Go語言的select語句及其在非同步中的應用,你可以把它想像成switch case的非同步版本
time

REF


上一篇
Day15. Go語言中的Goroutine介紹與使用
下一篇
Day17. select語句及其在非同步中的應用
系列文
可以Go一輩子嗎?31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言