golang開發:channel使用

2021-03-03 飛翔碼農

channel主要是用於多個goroutine之間通信

channel語法

channel是引用類型,需要實用make來創建channel,如下make(chan Type, [buffer])chan Type 通道的類型buffer 是可選參數,代表通道緩衝區的大小(省略則代表無緩衝)向channel裡面寫入數據使用 <- 符號

q := make(chan bool)

q<-true

從channel裡面讀取數據也是使用 <- 符號,只不過寫入的channel在右邊,讀取的時候channel在左邊。意思跟方向是一致的,一個是數據進入channel,一個是數據從channel出去

q := make(chan bool)

<-q

有緩衝channel的使用

我們一直使用的無緩衝的channel,今天主要學習下有緩存的channel。無緩衝的channel,寫入數據後一定要有goroutine 從channel讀取數據後再寫入,否則程序會panic。

func main() {

ch := make(chan int)

ch<-1

}

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:

有緩衝的channel,可以寫入緩衝大小個數據,可以沒有goroutine從channel讀取。

func main() {

ch := make(chan int,2)

ch<-1

ch<-2

}

Process finished with exit code 0

執行結果跟預期是一致的。

有緩衝大小的channel使用場景

假如我們有一個任務需要10個goroutine去調度執行,只要有一個goroutine執行完畢,調度就應該結束。我們看下偽代碼

func test(wg *sync.WaitGroup,ch chan int,i int) {

fmt.Println("test code")

ch<-i

}

func main() {

fmt.Println("start",runtime.NumGoroutine())

ch := make(chan int)

wg := new(sync.WaitGroup)

for i:=0;i<10;i++ {

wg.Add(1)

go test(wg,ch,i)

}

fmt.Println(<-ch)

fmt.Println("end",runtime.NumGoroutine())

wg.Done()

}

start 1

test code

9

end 10

從執行結果上看,是第9個goroutine首先執行完畢了。程序也正常退出了。但是我們看到,加上主goroutine,內存中一共有11個goroutine,程序退出的時候還有10個goroutine,減去一個主goroutine,還有9個goroutine沒有退出,這個對程序來說是不允許,可能會洩漏或者長期佔用資源不釋放。

但是我們如果使用了有緩衝的channel,就可以利用channel的緩衝機制正常退出全部的goroutine了。看下代碼

func test(wg *sync.WaitGroup,ch chan int,i int) {

ch<-i

}

func main() {

fmt.Println("start",runtime.NumGoroutine())

ch := make(chan int, 10)

wg := new(sync.WaitGroup)

for i:=0;i<10;i++ {

wg.Add(1)

go test(wg,ch,i)

}

fmt.Println(<-ch,"success")

for i:= 0;i<9;i++ {

fmt.Println(<-ch)

}

fmt.Println("end",runtime.NumGoroutine())

wg.Done()

}

start 1

0 success

1

2

4

3

5

6

7

8

9

end 1

Process finished with exit code 0

列印success的時候,第一個goroutine已經將任務完成,循環9次將channel裡面的數據讀取出來,保證創建的goroutine都不會阻塞能夠正常退出來。

相關焦點

  • 【Golang】圖解channel之數據結構
    channel被設計用來實現goroutine間的通信,按照golang的設計思想:以通信的方式共享內存。
  • 走進Golang之Channel的使用
    對於 Golang 語言應用層面的知識,先講如何正確的使用,然後再講它的實現。channel 是什麼Don't communicate by sharing memory, share memory by communicating.
  • 走進Golang之Channel的數據結構
    上篇文章講了 channel 的基本使用,講了一些使用時需要注意的事項,本文將重點介紹 channel 中的兩個數據結構:循環隊列 與 雙端鍊表 。其實有緩衝的 channel,就是把同步的通信變為了異步的通信。寫的 channel 不需要關注讀 channel,只要有空間它就寫;而讀也一樣,只要有數據就正常讀就可以,如果沒有就掛起到隊列中,等待被喚醒。下圖形象的展示了有緩衝 channel 是如何交換數據的。
  • Golang並發:再也不愁選channel還是選鎖
    在Golang裡,channel也不是萬能的,這是由channel的特性和局限造成的。下面就給大家介紹channel的特點、核心方法和缺點。channel解決並發問題的思路和示例channel的核心是數據流動,關注到並發問題中的數據流動,把流動的數據放到channel中,就能使用channel解決這個並發問題。
  • Golang 入門筆記 - Channel
    原文如下:Go 語言使用 goroutine 可以輕鬆地實現並發。大家應該都知道,goroutine 是通過 channel 實現相互通信的。channel 確保 goroutine 和主線程時間可以相互通信。在這篇文章中,將會與大家討論如何創建 channel 和實現數據共享。
  • 使用Golang快速構建WEB應用
  • 「Golang」for range 使用方法及避坑指南
    Go給我們提供了一個新關鍵字range來進行遍歷,可以把它理解為一個三段式循環的語法糖,它不光可以遍歷map和channel,同樣的也可以遍歷數組,切片等數據結構,但是與傳統循環不同的是,他不可以進行普通的次數循環,那麼接下來我們來看一下其遍歷數組,切片,map和channel的相關操作以及所能碰到的坑。
  • golang之context使用
    背景golang中並發編程的三種實現方式:chan管道、waitGroup和Context。本篇將重點介紹context的使用,告訴大家基本的使用方式,做到會用。Context概念介紹context譯為上下文,golang在1.6.2的時候還沒有自己的context,在1.7的版本中就把golang.org/x/net/context包被加入到了官方的庫中。golang 的 Context包,是專門用來處理多個goroutine之間與請求域的數據、取消信號、截止時間等相關操作。
  • Golang context你必須要知道的
    go1.6 及之前版本請使用 golang.org/x/net/context。go1.7 及之後已移到標準庫 context。go vet 工具檢查所有流程控制路徑上使用 CancelFuncs。使用context 是 Go 中廣泛使用的程序包,由 Google 官方開發,在 1.7 版本引入。
  • golang下文件鎖的使用
    前言題目是golang下文件鎖的使用,但本文的目的其實是通過golang下的文件鎖的使用方法,來一窺文件鎖背後的機制。
  • Golang 性能分析工具簡要介紹
    在開發 golang 程序過程中,go
  • gRPC 實操指南(golang)
    •C/S架構的傳輸業務,如股票軟體,每天需要用戶登陸的時候去伺服器拉取最新的數據,或者較簡單的文件傳輸業務,登陸驗證業務,證書業務都可以使用rpc的方式•跨語言開發的項目,比如web業務使用golang進行開發,底層使用cpp或c,部分腳本使用py,跨語言通信可以通過RPC提供的不同語言的開發機制進行實現。
  • Golang入門教程——map篇
    今天是golang專題的第7篇文章,我們來聊聊golang當中map的用法。map這個數據結構我們經常使用,存儲的是key-value的鍵值對。在C++/java當中叫做map,在Python中叫做dict。
  • Golang指南:頂級Golang框架、IDE和工具列表
    (點擊尾部閱讀原文前往)原文:https://dzone.com/articles/golang-guide-a-list-of-top-golang-frameworks-ides自推出以來,Google的Go程式語言(Golang)越來越受主流用戶的歡迎。
  • GoHub 更新至 0.6,在線 Golang 文檔閱讀
    GoHubWIP (尚在開發中...)GoHub 使用 Github REST API v3 提供在線 Golang 文檔閱讀.支持兩種結構:Object 單個文檔項目, 多個 Package 組成Array 文檔項目列表, 每個項目的地址和說明, 每個項目下必須有 golist.json例: 單個文檔項目, 使用 GoDocu 生成.
  • Golang入門教程——面向對象篇
    golang作為一門剛剛誕生十年的新興語言自然是支持面向對象的,但是golang當中面向對象的概念和特性與我們之前熟悉的大部分語言都不盡相同。比如Java、Python等,相比之下, golang這個部分的設計非常得簡潔和優雅(仁者見仁),所以即使你之前沒有系統地了解過面向對象,也沒有關係,也一定能夠看懂。
  • 【Golang】Context基礎篇
    一個接口golang的context包定義了Context類型,根據官方文檔的說法,該類型被設計用來在API邊界之間以及過程之間傳遞截止時間
  • Golang 需要避免踩的 50 個坑(二)
    最近準備寫一些關於golang的技術博文,本文是之前在GitHub上看到的golang技術譯文,感覺很有幫助,先給各位讀者分享一下。
  • Golang入門教程——基本操作篇
    首先是func關鍵字,我們使用這個關鍵字定義一個函數,之後跟著的是函數名,然後是函數的傳參,最後是函數的返回值。這個順序可能和我們之前普遍接觸的語法不太一樣,例如C++當中是把函數返回類型寫在最前面,然後是函數名和傳參。再比如Python當中則是沒有返回值的任何信息,只有def關鍵字和函數名以及傳入的參數。