go中channel簡單使用

2021-07-11 18:32:09 字數 4258 閱讀 4506

channel是go語言在語言級別提供的goroutine間的通訊機制。我們可以使用channel在兩個或者多個goroutine之間傳遞資訊。channel是程序內的通訊。

channel分為帶緩衝的以及不帶緩衝的。

ch:=make(chan int )建立乙個不帶緩衝的channel。ch:=make(chan int,2,5)建立乙個帶緩衝的channel,其中len(ch)是2,cap(ch)是5.

1.不帶緩衝的channel使用:

package main

import (

"fmt"

"time"

"runtime"

)func main()

func ff(ch chan int)

輸出:1 2016-05-12 12:50:02.4098584 +0800 cst

3 2016-05-12 12:50:02.4118585 +0800 cst

ff end

4 2016-05-12 12:50:04.4149731 +0800 cst

2 2016-05-12 12:50:04.4149731 +0800 cst

main end

5 2016-05-12 12:50:04.4149731 +0800 cst

根據時間可以分析一下程式的工作流程。首先main函式執行到ch<-2時候就阻塞了。不帶緩衝的channel接收資料後會阻塞,直到從這個channel中讀取資料後,阻塞的程式才恢復。等到ff函式執行到<-ch後,main函式才繼續執行。這是ff函式也在執行。從列印的時間可以看出兩個函式是併發的。

package main

import (

"fmt"

"time"

"runtime"

)func main()

func ff(ch chan int)

輸出:1 2016-05-12 13:03:00.3583545 +0800 cst

3 2016-05-12 13:03:00.3603546 +0800 cst

ff end

4 2016-05-12 13:03:02.3634692 +0800 cst

2 2016-05-12 13:03:02.3634692 +0800 cst

main end

5 2016-05-12 13:03:02.3634692 +0800 cst

根據列印的時間資訊可以分析,main函式在執行到<-ch時,阻塞。不帶緩衝的channel從中讀取資料時會阻塞,直到向其中寫入資料,阻塞的程式才會繼續執行。

2.帶緩衝的channel使用:

package main

import (

"fmt"

"time"

"runtime"

)func main()

func ff(ch chan int)

輸出:1 2016-05-12 13:07:27.0666093 +0800 cst

2 2016-05-12 13:07:27.0716096 +0800 cst

main end

5 2016-05-12 13:07:27.0716096 +0800 cst

根據列印資訊可以分析,main函式在執行到ch<-2的時候,沒有阻塞,而是繼續執行。那麼為什麼ff函式沒有來得及執行fmt.println("3", time.now())這條程式呢?

從上面不帶channel的程式可以看出,fmt.println("3", time.now())這句話執行的時間比fmt.println("1", time.now())這句話執行的時間要晚。晚多少時間和cpu有關。我們可以先不管。可以做出假設,ff函式裡面的fmt.println("3", time.now())還沒來得及執行,main函式就執行完了,程式就退出了。在這個過程中開的goroutine都不會執行,直接取消。

那麼,怎麼證明上面那段程式ff沒有執行是因為main結束了呢?可以在mian函式最後等待一小會。

修改上面的程式如下:

package main

import (

"fmt"

"time"

"runtime"

)func main()

func ff(ch chan int)

程式輸出:1 2016-05-12 13:17:44.0658997 +0800 cst

2 2016-05-12 13:17:44.0708999 +0800 cst

main end

5 2016-05-12 13:17:44.0708999 +0800 cst

3 2016-05-12 13:17:44.0678998 +0800 cst

可以看到,main最後等待了一秒時間,然後ff函式來得及執行fmt.println("3", time.now())。但是在ff函式執行time.sleep(2 * time.second)等待兩秒的時候,mian已經結束了。

更改一下channel讀取和寫入的順序,如下:

package main

import (

"fmt"

"time"

"runtime"

)func main()

func ff(ch chan int)

輸出:1 2016-05-12 13:20:06.0520208 +0800 cst

3 2016-05-12 13:20:06.055021 +0800 cst

ff end

4 2016-05-12 13:20:08.0571355 +0800 cst

2 2016-05-12 13:20:08.0571355 +0800 cst

main end

5 2016-05-12 13:20:08.0571355 +0800 cst

根據列印資訊可以分析,main函式在執行到<-ch這句話是阻塞,帶緩衝的channel如果裡面沒有資料,從中讀取的話會阻塞程式的執行。等到ff函式執行到ch <- 2時,main函式才從阻塞中恢復。

channel切片用例:

package main

import (

"fmt"

"time"

"runtime"

)func main()

fmt.println("main end")

fmt.println("5", time.now())

}func ff(ch chan int)

輸出:ff end

ff end

1 2016-05-12 18:40:47.5375708 +0800 cst

0x1165a1c0

0x1165a2c0

main end

5 2016-05-12 18:40:47.5425711 +0800 cst

使用range對channel操作時要注意。

package main

import (

"fmt"

"time"

"runtime"

)func main()

fmt.println("main end")

fmt.println("5", time.now())

}func ff(ch chan int)

輸出:ff end

1 2016-05-12 18:44:27.3991462 +0800 cst

1fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:

main.main()

f:/ccs/test.go:12 +0x169

exit status 2

exit status 1

程式修改一下,對於單個不帶緩衝的channel使用range時,channel需要close。

package main

import (

"fmt"

"time"

"runtime"

)func main()

fmt.println("main end")

fmt.println("5", time.now())

}func ff(ch chan int)

輸出:1 2016-05-12 18:46:47.4581571 +0800 cst

ff end

1main end

5 2016-05-12 18:46:47.4641574 +0800 cst

Go併發控制 channel

雖然上次提過的sync控制併發很簡單,但是他有一定的侷限性,他也只能控制能過讓所有的goroutine在程式結束時完成,並不能干涉各個goroutine,下面我們介紹一種更好的方式,就是利用通道 首先先說用channel控制併發在程式結束之前完成 func main ch sum fmt.print...

go語言 channel特點

通道擁有阻塞機制 無緩衝區 有緩衝區同理。接收端在傳送端資料傳送完成之前 通道為nil 處於阻塞狀態 傳送端在接收端資料拿走完成之前 通道為滿 處於阻塞態 1.struct 型別不佔空間,作為通道的一種訊號方式 2.chan型別為引用型別,故需要進行初始化,申請空間,在通道使用結束後close 關閉...

go中的Channel (總結於尚矽谷go)

channel是乙個資料型別,主要用來解決協程的同步問題以及協程之間資料共享 資料傳遞 的問題。可以把它看成管道,一端讀,一端寫 goroutine執行在相同的位址空間,因此訪問共享記憶體必須做好同步 goroutine 奉行通過通訊來共享記憶體,而不是共享記憶體來通訊。引 型別 channel可用...