Go語言入門學習之Channel通道詳解_第1頁
Go語言入門學習之Channel通道詳解_第2頁
Go語言入門學習之Channel通道詳解_第3頁
Go語言入門學習之Channel通道詳解_第4頁
Go語言入門學習之Channel通道詳解_第5頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

第Go語言入門學習之Channel通道詳解目錄前言通道的聲明通道的初始化發(fā)送和接收數(shù)據(jù)通道的關閉通道的容量與長度緩沖通道與無緩沖通道雙向通道和單向通道遍歷通道fibonacci數(shù)列參考文章:總結(jié)

前言

不同于傳統(tǒng)的多線程并發(fā)模型使用共享內(nèi)存來實現(xiàn)線程間通信的方式,go是通過channel進行協(xié)程(goroutine)之間的通信來實現(xiàn)數(shù)據(jù)共享。

channel,就是一個管道,可以想像成Go協(xié)程之間通信的管道。它是一種隊列式的數(shù)據(jù)結(jié)構,遵循先入先出的規(guī)則。

通道的聲明

每個通道都只能傳遞一種數(shù)據(jù)類型的數(shù)據(jù),聲明時需要指定通道的類型。chanType表示Type類型的通道。通道的零值為nil。

varchannel_namechanchannel_types

varstrchanstring

通道的初始化

聲明完通道后,通道的值為nil,不能直接使用,使用make函數(shù)對通道進行初始化操作。

channel_name=make(chanchannel_type)

str=make(chanstring)

或者

str:=make(chanstring)

發(fā)送和接收數(shù)據(jù)

發(fā)送數(shù)據(jù),把data數(shù)據(jù)發(fā)送到channel_name通道中。

channel_name-data

接收數(shù)據(jù),從channel_name通道中接收數(shù)據(jù)到value。

value:=-channel_name

funcPrintFunc(cchanstring){

c-"往通道里面?zhèn)鲾?shù)據(jù)"

funcmain(){

str:=make(chanstring)

fmt.Println("start")

goPrintFunc(str)

result:=-str

fmt.Println(result)

fmt.Println("end")

}

發(fā)送與接收默認是阻塞的。如果從通道接收數(shù)據(jù)沒接收完主協(xié)程是不會繼續(xù)執(zhí)行下去的。當把數(shù)據(jù)發(fā)送到通道時,會在發(fā)送數(shù)據(jù)的語句處發(fā)生阻塞,直到有其它協(xié)程從通道讀取到數(shù)據(jù),才會解除阻塞。與此類似,當讀取通道的數(shù)據(jù)時,如果沒有其它的協(xié)程把數(shù)據(jù)寫入到這個通道,那么讀取過程就會一直阻塞著。

通道的關閉

對于一個已經(jīng)使用完畢的通道,我們要將其進行關閉。對于一個已經(jīng)關閉的通道如果再次關閉會導致報錯。

close(channel_name)

可以在接收數(shù)據(jù)時,判斷通道是否已經(jīng)關閉,從通道讀取數(shù)據(jù)返回的第二個值表示通道是否沒被關閉,如果已經(jīng)關閉,返回值為false;如果還未關閉,返回值為true。

value,ok:=-channel_name

通道的容量與長度

通道可以設置緩沖區(qū),通過make的第二個參數(shù)指定緩沖區(qū)大小

ch:=make(chanint,100)

0:通道中不能存放數(shù)據(jù),在發(fā)送數(shù)據(jù)時,必須要求立馬接收,否則會報錯。此時的通道稱之為無緩沖通道。1:通道只能緩存一個數(shù)據(jù),若通道中已有一個數(shù)據(jù),此時再往里發(fā)送數(shù)據(jù),會造成程序阻塞。利用這點可以利用通道來做鎖。大于1:通道中可以存放多個數(shù)據(jù),可以用于多個協(xié)程之間的通信管道,共享資源。

通過cap函數(shù)和len函數(shù)獲取通道的容量和長度。

funcmain(){

//創(chuàng)建一個通道

c:=make(chanint,5)

fmt.Println("初始化:")

fmt.Println("cap:",cap(c))

fmt.Println("len:",len(c))

c-1

c-2

c-3

fmt.Println("傳入數(shù)據(jù):")

fmt.Println("cap:",cap(c))

fmt.Println("len:",len(c))

fmt.Println("取出一個數(shù):")

fmt.Println("cap:",cap(c))

fmt.Println("len:",len(c))

}

緩沖通道與無緩沖通道

帶緩沖區(qū)的通道允許發(fā)送端的數(shù)據(jù)發(fā)送和接收端的數(shù)據(jù)獲取處于異步狀態(tài),就是說發(fā)送端發(fā)送的數(shù)據(jù)可以放在緩沖區(qū)里面,可以等待接收端去獲取數(shù)據(jù),而不是立刻需要接收端去獲取數(shù)據(jù)。

不過由于緩沖區(qū)的大小是有限的,所以還是必須有接收端來接收數(shù)據(jù)的,否則緩沖區(qū)一滿,數(shù)據(jù)發(fā)送端就無法再發(fā)送數(shù)據(jù)了。

通道不帶緩沖,發(fā)送方會阻塞直到接收方從通道中接收了值。如果通道帶緩沖,發(fā)送方則會阻塞直到發(fā)送的值被拷貝到緩沖區(qū)內(nèi);如果緩沖區(qū)已滿,則意味著需要等待直到某個接收方獲取到一個值。接收方在有值可以接收之前會一直阻塞。

c:=make(chanint)

//或者

c:=make(chanint,0)

緩沖通道允許通道里存儲一個或多個數(shù)據(jù),設置緩沖區(qū)后,發(fā)送端和接收端可以處于異步的狀態(tài)。

c:=make(chanint,3)

雙向通道和單向通道

雙向通道:既可以發(fā)送數(shù)據(jù)也可以接收數(shù)據(jù)

funcmain(){

//創(chuàng)建一個通道

c:=make(chanint)

//發(fā)送數(shù)據(jù)

gofunc(){

fmt.Println("send:1")

c-1

//接收數(shù)據(jù)

gofunc(){

n:=-c

fmt.Println("receive:",n)

//主協(xié)程休眠

time.Sleep(time.Millisecond)

}

單向通道:只能發(fā)送或者接收數(shù)據(jù)。具體細分為只讀通道和只寫通道。

-chan表示只讀通道:

//定義只讀通道

c:=make(chanstring)

//定義類型

typeReceiver=-chanstring

varreceiverReceiver=c

//或者簡單寫成下面的形式

typeReceiver=-chanint

receiver:=make(Receiver)

chan-表示只寫通道:

//定義只寫通道

c:=make(chanint)

//定義類型

typeSender=chan-int

varsenderSender=c

//或者簡單寫成下面的形式

typeSender=chan-int

sender:=make(Sender)

packagemain

import(

"fmt"

"time"

//Sender只寫通道類型

typeSender=chan-string

//Receiver只讀通道類型

typeReceiver=-chanstring

funcmain(){

//創(chuàng)建一個雙向通道

varch=make(chanstring)

//開啟一個協(xié)程

gofunc(){

//只寫通道

varsenderSender=ch

fmt.Println("writeonlystart:")

sender-"Go"

//開啟一個協(xié)程

gofunc(){

//只讀通道

varreceiverReceiver=ch

message:=-receiver

fmt.Println("readonlystart:",message)

time.Sleep(time.Millisecond)

}

遍歷通道

使用forrange循環(huán)可以遍歷通道,但在遍歷時要確保通道是處于關閉狀態(tài),否則循環(huán)會被阻塞。

packagemain

import(

"fmt"

funcloopPrint(cchanint){

fori:=0;ii++{

c-i

//記得要關閉通道

//否則主協(xié)程遍歷完不會結(jié)束,而會阻塞

close(c)

funcmain(){

//創(chuàng)建一個通道

varch2=make(chanint,5)

goloopPrint(ch2)

forv:=rangech2{

fmt.Println(v)

}

fibonacci數(shù)列

packagemain

import(

"fmt"

funcfibonacci(nint,cchanint){

x,y:=0,1

fori:=0;ii++{

c-x

x,y=y,x+y

close(c)

funcmain(){

c:=make(chanint,10)

gofibonacci(cap(c),c)

//range函數(shù)遍歷每個從通道接收到的數(shù)據(jù),因為c在發(fā)送完1

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論