tft每日頭條

 > 生活

 > golang channel詳細解析

golang channel詳細解析

生活 更新时间:2024-08-22 12:20:39

golang channel詳細解析?今天是golang專題的第14篇文章,大家可以點擊上方的專輯回顧之前的内容,我來為大家科普一下關于golang channel詳細解析?以下内容希望對你有幫助!

golang channel詳細解析(簡介channel常見用法完成goroutin通信)1

golang channel詳細解析

今天是golang專題的第14篇文章,大家可以點擊上方的專輯回顧之前的内容。

今天我們來看看golang當中另一個很重要的概念——信道。我們之前介紹goroutine的時候曾經提過一個問題,當我們啟動了多個goroutine之後,我們怎麼樣讓goroutine之間保持通信呢?

要回答這個問題就需要用到信道。

channel

信道的英文是channel,在golang當中的關鍵字是chan。它的用途是用來在goroutine之間傳輸數據,這裡你可能要問了,為什麼一定得是goroutine之間傳輸數據呢,函數之間傳遞不行嗎?

因為正常的傳輸數據直接以參數的形式傳遞就可以了,隻有在并發場景當中,多個線程彼此隔離的情況下,才需要一個特殊的結構傳輸數據。

Chan看起來比較怪,在其他語言當中基本沒有出現過,但是它的原理和使用都非常簡單。

我們先來看它的使用,首先是定義一個chan,還是老規矩,通過make關鍵字創建。我們之前也提過,golang當中的一個設計原則就是能省則省,能簡單則簡單。從這個make關鍵字就看得出來,它可以創建的東西太多了,既可以創建一個切片,也可以創建map,還可以創建信道。

所以當我們要創建一個chan的時候,可以通過make實現。

Ch := make(chan int)

我們在chan後面跟上一個類型,表示這個信道傳輸的數據類型。如果你想要傳輸任何類型呢,那可以用我們之前說過的interface{}。

Chan創建了之後,我們想要從其中獲取數據或者是把數據放入其中也非常簡單,簡單到都沒有api,直接用形象的傳輸語句就可以了。

比如我們現在有一個chan是ch,我們想要放入數據,我們可以這樣ch <- a。我們想要從ch當中獲取數據,我們可以v := <- ch。

我們用箭頭表示數據的流動,是不是很形象很直觀呢?

阻塞

但是還沒完,chan有一個很關鍵的點在于,chan的使用是阻塞的。也就是說下遊從chan當中拿走一個數據我們才可以傳入一個數據。否則的話,傳輸數據的代碼就會一直等待chan清空。

同樣,如果我們定義了一個從chan當中讀取數據的語句,假如當前的chan是空的話,那麼它也會一直阻塞等待,直到chan當中有數據了為止。

所以我們就知道了,chan的使用場景當中需要一個生産方,也需要一個消費方。我們來看一個golang官方的一個例子:

package main import "fmt" func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum = v } c <- sum // 将和送入 c } func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c // 從 c 中接收 fmt.Println(x, y, x y) }

我們啟動了兩個goroutine去對數組進行求和并進行返回,goroutine生産的數據是沒辦法直接return的,所以隻能通過chan的形式傳輸出來。chan傳輸出來需要下遊消費,所以上面兩個goroutine的數據會傳輸到x, y: <-c, <-c 這一句語句當中。

前面說過了,chan的傳輸是阻塞的,所以這一句語句會一直等待,直到上面兩個goroutine都計算完成了為止。

如果你看的有些發蒙,覺得好似有些理解了又好似沒有的話,那麼很簡單的一個辦法是在理解的時候把這個使用場景做一個變幻。把chan的使用場景想象成我們之前介紹過的生産者消費者設計模式,chan在其中扮演的角色其實就是隊列。

生産者往隊列當中傳輸數據,消費者進行消費,唯一不同的是這個隊列的容量是1,必須要生産和消費端都準備就緒了才會進行數據傳輸。

chan的緩沖

前文說了,chan的容量隻有1,隻有消費端和生産端都就緒的時候才可以傳輸數據。我們也可以給chan加上緩沖,如果消費端來不及把所有的數據都消費完,允許生産端先把數據暫時存在chan當中,先不發生阻塞,隻有在chan滿了之後才會阻塞。

用法也很簡單,我們在通過make創建chan的時候多加上一個參數表示容量即可,和我們之前創建切片的道理很類似。

Ch := make(chan int, 100)

比如這樣,我們就創建了一個緩沖區為100的信道。

但多說一句,其實這種情況不太常用,原因也很簡單。因為上下遊的消費情況是統一的,如果生産者生産的速度過快,而消費端跟不上的話,即使把它先暫存在緩沖區當中也沒什麼用,早晚還是會要阻塞的。

close

當我們對信道使用結束之後,可以通過close語句将它關閉。

Close這個操作隻能在生産端進行,消費端如果close信道會引發一個panic。我們在從chan接收數據的時候,可以加上一個參數判斷信道是否關閉。

v, ok := <- ch if !ok { return }

這樣我們就可以判斷chan關閉的時間了。

今天的文章到這裡就結束了,如果喜歡本文的話,請來一波素質三連,給我一點支持吧(關注、轉發、點贊)。

相關閱讀

Python | 面試的常客,經典的生産消費者模式

本文始發于公衆号:TechFlow

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved