婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Go語言中 Channel 詳解

Go語言中 Channel 詳解

熱門標簽:南通如皋申請開通400電話 中國地圖標注省會高清 廣州呼叫中心外呼系統 地圖標注的汽車標 高德地圖標注口訣 學海導航地圖標注 浙江高速公路地圖標注 江西轉化率高的羿智云外呼系統 西部云谷一期地圖標注

Channel是Go中的一個核心類型,你可以把它看成一個管道,通過它并發核心單元就可以發送或者接收數據進行通訊(communication)。

它的操作符是箭頭 - 。

ch - v    // 發送值v到Channel ch中
v := -ch  // 從Channel ch中接收數據,并將數據賦值給v
(箭頭的指向就是數據的流向)

就像 map 和 slice 數據類型一樣, channel必須先創建再使用:

ch := make(chan int)
Channel類型
Channel類型的定義格式如下:

ChannelType = ( "chan" | "chan" "-" | "-" "chan" ) ElementType .
它包括三種類型的定義。可選的-代表channel的方向。如果沒有指定方向,那么Channel就是雙向的,既可以接收數據,也可以發送數據。

chan T          // 可以接收和發送類型為 T 的數據
chan- float64  // 只可以用來發送 float64 類型的數據
-chan int      // 只可以用來接收 int 類型的數據
-總是優先和最左邊的類型結合。(The - operator associates with the leftmost chan possible)

chan- chan int    // 等價 chan- (chan int)
chan- -chan int  // 等價 chan- (-chan int)
-chan -chan int  // 等價 -chan (-chan int)
chan (-chan int)

使用make初始化Channel,并且可以設置容量:

make(chan int, 100)

容量(capacity)代表Channel容納的最多的元素的數量,代表Channel的緩存的大小。
如果沒有設置容量,或者容量設置為0, 說明Channel沒有緩存,只有sender和receiver都準備好了后它們的通訊(communication)才會發生(Blocking)。如果設置了緩存,就有可能不發生阻塞, 只有buffer滿了后 send才會阻塞, 而只有緩存空了后receive才會阻塞。一個nil channel不會通信。

可以通過內建的close方法可以關閉Channel。

你可以在多個goroutine從/往 一個channel 中 receive/send 數據, 不必考慮額外的同步措施。

Channel可以作為一個先入先出(FIFO)的隊列,接收的數據和發送的數據的順序是一致的。

channel的 receive支持 multi-valued assignment,如

v, ok := -ch
它可以用來檢查Channel是否已經被關閉了。

send語句

send語句用來往Channel中發送數據, 如ch - 3。
它的定義如下:

SendStmt = Channel "-" Expression .
Channel  = Expression .

在通訊(communication)開始前channel和expression必選先求值出來(evaluated),比如下面的(3+4)先計算出7然后再發送給channel。

c := make(chan int)
defer close(c)
go func() { c - 3 + 4 }()
i := -c
fmt.Println(i)

send被執行前(proceed)通訊(communication)一直被阻塞著。如前所言,無緩存的channel只有在receiver準備好后send才被執行。如果有緩存,并且緩存未滿,則send會被執行。

往一個已經被close的channel中繼續發送數據會導致run-time panic。

往nil channel中發送數據會一致被阻塞著。

receive 操作符

-ch用來從channel ch中接收數據,這個表達式會一直被block,直到有數據可以接收。
從一個nil channel中接收數據會一直被block。

從一個被close的channel中接收數據不會被阻塞,而是立即返回,接收完已發送的數據后會返回元素類型的零值(zero value)。

如前所述,你可以使用一個額外的返回參數來檢查channel是否關閉。

x, ok := -ch
x, ok = -ch
var x, ok = -ch

如果OK 是false,表明接收的x是產生的零值,這個channel被關閉了或者為空。

blocking

缺省情況下,發送和接收會一直阻塞著,直到另一方準備好。這種方式可以用來在gororutine中進行同步,而不必使用顯示的鎖或者條件變量。

如官方的例子中x, y := -c, -c這句會一直等待計算結果發送到channel中。

import "fmt"
func sum(s []int, c chan int) {
 sum := 0
 for _, v := range s {
  sum += v
 }
 c - sum // send sum to 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 // receive from c
 fmt.Println(x, y, x+y)
}
Buffered Channels

make的第二個參數指定緩存的大小:ch := make(chan int, 100)。

通過緩存的使用,可以盡量避免阻塞,提供應用的性能。

Range

for …… range語句可以處理Channel。

func main() {
 go func() {
  time.Sleep(1 * time.Hour)
 }()
 c := make(chan int)
 go func() {
  for i := 0; i 10; i = i + 1 {
   c - i
  }
  close(c)
 }()
 for i := range c {
  fmt.Println(i)
 }
 fmt.Println("Finished")
}

range c產生的迭代值為Channel中發送的值,它會一直迭代直到channel被關閉。上面的例子中如果把close(c)注釋掉,程序會一直阻塞在for …… range那一行。

select

select語句選擇一組可能的send操作和receive操作去處理。它類似switch,但是只是用來處理通訊(communication)操作。
它的case可以是send語句,也可以是receive語句,亦或者default。

receive語句可以將值賦值給一個或者兩個變量。它必須是一個receive操作。

最多允許有一個default case,它可以放在case列表的任何位置,盡管我們大部分會將它放在最后。

import "fmt"
func fibonacci(c, quit chan int) {
 x, y := 0, 1
 for {
  select {
  case c - x:
   x, y = y, x+y
  case -quit:
   fmt.Println("quit")
   return
  }
 }
}
func main() {
 c := make(chan int)
 quit := make(chan int)
 go func() {
  for i := 0; i 10; i++ {
   fmt.Println(-c)
  }
  quit - 0
 }()
 fibonacci(c, quit)
}

如果有同時多個case去處理,比如同時有多個channel可以接收數據,那么Go會偽隨機的選擇一個case處理(pseudo-random)。如果沒有case需要處理,則會選擇default去處理,如果default case存在的情況下。如果沒有default case,則select語句會阻塞,直到某個case需要處理。

需要注意的是,nil channel上的操作會一直被阻塞,如果沒有default case,只有nil channel的select會一直被阻塞。

select語句和switch語句一樣,它不是循環,它只會選擇一個case來處理,如果想一直處理channel,你可以在外面加一個無限的for循環:

for {
 select {
 case c - x:
  x, y = y, x+y
 case -quit:
  fmt.Println("quit")
  return
 }
}

timeout

select有很重要的一個應用就是超時處理。 因為上面我們提到,如果沒有case需要處理,select語句就會一直阻塞著。這時候我們可能就需要一個超時操作,用來處理超時的情況。
下面這個例子我們會在2秒后往channel c1中發送一個數據,但是select設置為1秒超時,因此我們會打印出timeout 1,而不是result 1。

import "time"
import "fmt"
func main() {
    c1 := make(chan string, 1)
    go func() {
        time.Sleep(time.Second * 2)
        c1 - "result 1"
    }()
    select {
    case res := -c1:
        fmt.Println(res)
    case -time.After(time.Second * 1):
        fmt.Println("timeout 1")
    }
}

其實它利用的是time.After方法,它返回一個類型為-chan Time的單向的channel,在指定的時間發送一個當前時間給返回的channel中。

Timer和Ticker

我們看一下關于時間的兩個Channel。
timer是一個定時器,代表未來的一個單一事件,你可以告訴timer你要等待多長時間,它提供一個Channel,在將來的那個時間那個Channel提供了一個時間值。下面的例子中第二行會阻塞2秒鐘左右的時間,直到時間到了才會繼續執行。

timer1 := time.NewTimer(time.Second * 2)
-timer1.C
fmt.Println("Timer 1 expired")

當然如果你只是想單純的等待的話,可以使用time.Sleep來實現。

你還可以使用timer.Stop來停止計時器。

timer2 := time.NewTimer(time.Second)
go func() {
 -timer2.C
 fmt.Println("Timer 2 expired")
}()
stop2 := timer2.Stop()
if stop2 {
 fmt.Println("Timer 2 stopped")
}

ticker是一個定時觸發的計時器,它會以一個間隔(interval)往Channel發送一個事件(當前時間),而Channel的接收者可以以固定的時間間隔從Channel中讀取事件。下面的例子中ticker每500毫秒觸發一次,你可以觀察輸出的時間。

ticker := time.NewTicker(time.Millisecond * 500)
go func() {
 for t := range ticker.C {
  fmt.Println("Tick at", t)
 }
}()

類似timer, ticker也可以通過Stop方法來停止。一旦它停止,接收者不再會從channel中接收數據了。

close

內建的close方法可以用來關閉channel。

總結一下channel關閉后sender的receiver操作。
如果channel c已經被關閉,繼續往它發送數據會導致panic: send on closed channel:

import "time"
func main() {
 go func() {
  time.Sleep(time.Hour)
 }()
 c := make(chan int, 10)
 c - 1
 c - 2
 close(c)
 c - 3
}

但是從這個關閉的channel中不但可以讀取出已發送的數據,還可以不斷的讀取零值:

c := make(chan int, 10)
c - 1
c - 2
close(c)
fmt.Println(-c) //1
fmt.Println(-c) //2
fmt.Println(-c) //0
fmt.Println(-c) //0

但是如果通過range讀取,channel關閉后for循環會跳出:

c := make(chan int, 10)
c - 1
c - 2
close(c)
for i := range c {
 fmt.Println(i)
}

通過i, ok := -c可以查看Channel的狀態,判斷值是零值還是正常讀取的值。

c := make(chan int, 10)
close(c)
i, ok := -c
fmt.Printf("%d, %t", i, ok) //0, false

同步

channel可以用在goroutine之間的同步。
下面的例子中main goroutine通過done channel等待worker完成任務。 worker做完任務后只需往channel發送一個數據就可以通知main goroutine任務完成。

import (
 "fmt"
 "time"
)
func worker(done chan bool) {
 time.Sleep(time.Second)
 // 通知任務已完成
 done - true
}
func main() {
 done := make(chan bool, 1)
 go worker(done)
 // 等待任務完成
 -done
}

您可能感興趣的文章:
  • golang判斷chan channel是否關閉的方法
  • Golang中channel使用的一些小技巧
  • Go語言的管道Channel用法實例
  • Golang優雅關閉channel的方法示例
  • golang中單向channel的語法介紹
  • 淺談Go Channel 高級實踐
  • Go中Channel發送和接收操作指南

標簽:東營 德宏 曲靖 貴州 保定 許昌 吐魯番 常州

巨人網絡通訊聲明:本文標題《Go語言中 Channel 詳解》,本文關鍵詞  語,言中,Channel,詳解,語,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Go語言中 Channel 詳解》相關的同類信息!
  • 本頁收集關于Go語言中 Channel 詳解的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    亚洲欧美日韩国产综合| 成人影视亚洲图片在线| 白白色亚洲国产精品| 色综合亚洲欧洲| 国产真实精品久久二三区| 视频一区欧美精品| 六月婷婷色综合| 久久99精品久久久| 日本欧美一区二区三区乱码 | 国产精品久久久久久久久免费樱桃| 中文字幕在线一区| 午夜精品视频在线观看| 国产一区二区不卡在线| 久久精品72免费观看| 99久久99久久综合| 日本一区二区三区在线观看| 美女国产一区二区| 色综合天天视频在线观看 | 欧美猛男gaygay网站| www欧美成人18+| 亚洲成人免费在线观看| 成人高清视频免费观看| 国产精品久久久久永久免费观看| 欧美视频你懂的| 中文字幕中文乱码欧美一区二区| 亚洲超丰满肉感bbw| 午夜精品久久久久久不卡8050| 视频在线在亚洲| 亚洲精品久久7777| 国产自产高清不卡| 午夜国产不卡在线观看视频| 黄一区二区三区| 欧美喷潮久久久xxxxx| 亚洲人精品午夜| 激情图片小说一区| 欧美va在线播放| 国产一区二区三区不卡在线观看| 日韩一区二区中文字幕| 视频一区视频二区中文字幕| 91精品国产一区二区三区蜜臀 | 91精品欧美久久久久久动漫| 日本电影亚洲天堂一区| 91麻豆精品秘密| 国产精品美女www爽爽爽| 欧美日韩五月天| 国产视频视频一区| 99久久久久久| 久久99精品久久只有精品| 国产亚洲精品超碰| 欧美综合视频在线观看| 丝袜诱惑亚洲看片| 国产日产欧美一区| 欧美日韩国产经典色站一区二区三区| 欧美一级日韩免费不卡| 国产.精品.日韩.另类.中文.在线.播放| 国产精品欧美一区二区三区| 51精品秘密在线观看| 一本久久a久久免费精品不卡| 中文字幕巨乱亚洲| 日韩美女视频一区二区在线观看| 色婷婷久久久综合中文字幕| 国产suv精品一区二区三区| 99国产精品国产精品毛片| 久久激五月天综合精品| 日韩av午夜在线观看| 欧美午夜不卡视频| eeuss影院一区二区三区| 黑人巨大精品欧美黑白配亚洲| 亚洲国产精品视频| 国产丝袜欧美中文另类| 欧美怡红院视频| 国产a视频精品免费观看| 丝袜亚洲另类欧美| 青青草一区二区三区| 亚洲一区免费观看| 亚洲国产成人91porn| 国产精品看片你懂得| 成人欧美一区二区三区在线播放| 精品一区二区三区久久| 国产专区综合网| 久久亚洲综合av| 国产日韩v精品一区二区| 欧美日韩你懂的| 欧美日韩在线播放一区| 日韩欧美aaaaaa| 日本一区二区三区高清不卡| 亚洲视频一区在线| 日韩专区一卡二卡| 国产精品夜夜爽| 欧美三区在线观看| 久久久久久久久久久黄色| 粉嫩av亚洲一区二区图片| 国产成人高清在线| 色嗨嗨av一区二区三区| 欧美一区二区三区免费视频| 中文字幕欧美国产| 色欧美片视频在线观看| 亚洲欧美成aⅴ人在线观看| 亚洲欧洲国产日韩| 久久国产欧美日韩精品| 欧美色手机在线观看| 国产精品天天看| 91丝袜国产在线播放| 精品成人一区二区三区四区| 亚洲综合色婷婷| 91美女片黄在线观看91美女| 国产大片一区二区| 欧美日韩午夜在线视频| 国产精品久久三区| 国产精品自产自拍| 精品国产sm最大网站免费看| 一区二区三区精品视频| 色综合色综合色综合色综合色综合| 亚洲五月六月丁香激情| 亚洲成人免费观看| 99这里只有久久精品视频| 国产盗摄女厕一区二区三区| 欧美一区二区三区啪啪| 久久国产视频网| 久久亚洲精品小早川怜子| 首页亚洲欧美制服丝腿| 精品视频一区二区不卡| 三级久久三级久久久| 奇米在线7777在线精品| 欧美一级生活片| 国内精品久久久久影院色| 国产欧美视频一区二区三区| 国产一区二区三区久久久| 亚洲精品久久嫩草网站秘色| 成人综合婷婷国产精品久久 | 国产在线不卡视频| 国产精品女同互慰在线看| 国产精品国模大尺度视频| 99久久伊人久久99| 欧美日韩一区三区| 久久激情五月激情| 亚洲男人天堂一区| 久久免费看少妇高潮| 91免费视频网| 激情综合网av| 亚洲欧洲综合另类| 精品久久久三级丝袜| 色综合色狠狠综合色| 国产一区二区三区四区五区入口 | 欧美日本精品一区二区三区| 韩国成人福利片在线播放| 一区二区三区四区五区视频在线观看 | 久久久精品国产免大香伊| 丁香网亚洲国际| 国产一区二区三区久久悠悠色av| 亚洲欧美另类小说视频| 久久久99精品免费观看| 欧美大胆一级视频| 免费成人深夜小野草| 国产精品久久久久久久久动漫| 另类小说综合欧美亚洲| 亚洲国产日韩在线一区模特| 久久精品99久久久| 在线视频你懂得一区| 另类人妖一区二区av| 日本女人一区二区三区| 午夜视频在线观看一区二区三区| 中文字幕一区二区视频| 中文字幕欧美一区| 美女免费视频一区二区| 日韩视频一区在线观看| 精品国产sm最大网站| 中文字幕一区不卡| 中文字幕在线免费不卡| 波多野结衣中文字幕一区二区三区| 91日韩一区二区三区| 日韩一区二区麻豆国产| 亚洲精品在线免费播放| 中文字幕色av一区二区三区| 亚洲国产一区二区视频| 日韩欧美高清一区| 亚洲自拍另类综合| 国产成人高清视频| 精品国产百合女同互慰| 奇米影视一区二区三区小说| 欧美日韩在线观看一区二区| 久久久激情视频| 秋霞电影一区二区| 欧美色精品天天在线观看视频| 一区二区三区在线观看视频| 在线免费精品视频| 一区二区三区不卡视频| 95精品视频在线| 一区二区免费在线播放| 色悠悠久久综合| 亚洲国产日韩av| 精品国产123| 亚洲女人****多毛耸耸8| 成人精品国产免费网站| 国产精品欧美极品| 欧美日韩免费高清一区色橹橹 | 国产成人啪免费观看软件 | 中文字幕五月欧美| 色综合久久六月婷婷中文字幕| 亚洲卡通欧美制服中文|