Golang 併發以及通道的使用方式

2022-09-21 17:12:14 字數 2877 閱讀 3641

golang最擅長的就是併發程式設計,使用golang可以很方便的進行併發程式設計。先看一段普通的**

package main

import (

"f""time")

func foo(i int)

func main()

}輸出為0 will sleep

0 wake up

1 will sleep

1 wake up

2 will sleep

2 wake up

3 will sleep

3 wake up

4 will sleep

4 wake up

大概要執行25秒的時間,因為我們的foo中休眠5s,5次迴圈,去掉其他時間至少需要25秒時間執行完成。

現在,我們希望併發呼叫foo函式,很簡單,使用go關鍵字建立協程(協程比執行緒的執行更加輕量級)

package main

import (

"fmt"

"time"

) func foo(i int)

func main()

time.sleep(10 * time.second)

}在呼叫foo前使用了go,這樣就會併發執行,最後新增休眠10秒,是防止主程序結束,協程也被銷毀。

package main

import (

"fmt"

"time")

func foo(i int, ch chan int)

count := 0

for count < 5 {

count +=

通道屬於復合型別,我們使用make函式建立通道,通道型別是int,也就是我們可以使用該通道傳遞int型別的值。

我們在主函式中向foo函式傳遞通道作為引數,當foo函式執行結束後,通過通道傳送數字1(ch

當五個協程都執行結束後退出迴圈。使用通道,我們還可以實現生產者和消費者模式。

package main

import (

"fmt"

"math/rand")

func consumer(ch www.cppcns.com producer(ch)

go consumer(ch, result)

fmt.printf("result: %d\n",

我們在生產者和消費者之間使用ch通道傳遞資料,使用reslut通道給主函式返回結果。注意觀察consumer函式和producer函式的引數列表,這裡通道引數的傳遞略有不同,指明了通道的方向,chan

可以看到,go語言實現併發非常簡單,借用通道,又可以在不同的協程之間方便的傳輸資料。

補充:golang通道的定義

先上一段**,

func main() {

// 示例1

//通道是乙個先進先出(fifo)的佇列

channel := make(chan int,3)

channel

go 語言自帶的唯一乙個併發安全性的型別

定義:使用go的內建函式make, chan 是關鍵字, int是通道型別的資料,3是通道容量大小,不能小於0,如果為0,則表示非緩衝通道。

1. 通道中傳送操作是互斥的,接收操作也是互斥的,比如上面,往channel中傳送1,2,3,這發生再三個時刻,同一時刻你不可能傳送1同時傳送2,接收操作也是同樣的道理。

2. 傳送和接收操作對同乙個元素是原子性的,就是說上面市不可能往channe1中傳送1的同時又把1從channel取出來,只有1這個元素完整的複製進channel中時,你才可以取出1這個元素來

3程式設計客棧. 傳送操作在完成之前會被阻塞,接收操作也是同理,比如你把1往channel完完整整地複製進去通道,這需要時間,在這個時間內,channel

以上這三個性質,隱約的感覺到了,就是為了實現互斥同時保證元素的安全性

通道元素值移動的過程:比如把1傳送到channel中,首先元素1複製乙個副本傳送到通道,等到要取走時,通道的副本1再複製乙個副本2,給要取值的對方,等到對方完全取走後,通道裡的副本1才會被刪除。

func main() {

// 示例2

channel := make(chan int,3)

channel

發生在通道快取已滿,但還忘通道裡面傳送元素,比如注釋中的"報錯1"處,因為通道的容量就是3,你寫了1,2,3之後再往裡面寫這時就寫不進一直阻塞再那裡

傳送再通道快取已空,但是還想從通道中取值,比如注釋中的"報錯2"處,此時你已取走了1,2,3,你再取值時,已經為空就一直阻 塞再那裡

對於非緩衝通道,比如示例3,定義了乙個channel2通道,容量為0,程式執行到「channel2

func main() {

// 示例4

channel3 := make(chan int,2)

channel3 程式設計客棧

close(channel5)

v3,b3 :=

往乙個已經關閉了的通道裡面傳送值時會引發「panic」。比如上面注釋報錯3處,前面已執行「close(channel3)」關閉通道操作,再往裡面傳送值就會引發panic。

關閉乙個已經關閉的通道時,會引發「panic」。比如上面注釋「報錯4」處。

示例5和示例6的區別僅僅在於關閉通道後,裡面是否還有值剩餘?假設有剩餘,我們就可以從通道取值同時賦給兩個變數,第二個變數是bool型別值,其為true表示取到了值,其為false表示沒有取到值,這樣僅僅可以避免引發「panic」,如果通道已經關閉且無元素值,則取出的第二個bool值為false;若從已關閉的通道裡面(裡面無剩餘元素值)再次讀取元素值,則第二個值為true。

總結:第二個bool值為false,則通道肯定關閉了,值為true,可能關閉也可能沒有關閉

本文標題: golang 併發以及通道的使用方式

本文位址:

Golang併發以及通道的使用

golang最擅長的就是併發程式設計,使用golang可以很方便的進行併發程式設計。先看一段普通的 package main import fmt time func foo i int func main 輸出為 0 will sleep 0 wake up 1 will sleep 1 wake...

Golang併發 goroutine和通道

goroutine 和通道 channel 實現的通訊順序程序 csp 模式 共享記憶體多執行緒模式 goroutine goroutine指每乙個併發執行的活動。main函式在主goroutine中執行。goroutine通過go關鍵字建立。gof 新建乙個goroutine呼叫f go語句本身立...

Golang併發控制 context的使用

我們已經知道waitgroup可以用於併發控制,但當遇到更複雜的場景時,例如主動取消goroutine或者使超時的goroutine自動退出等,waitgroup就無能為力。這個時候,就是context大有用武之地。包context定義了context型別,它跨api邊界和程序之間攜帶截止日期,取消...