Go 中的通道

2021-09-27 10:22:30 字數 2339 閱讀 1820

從底層實現上來看,通道只是乙個佇列。同步模式下,傳送和接收雙方配對,然後直接複製資料給對方。如配對失敗,則置入等待佇列,直到另一方出現後才會喚醒。非同步模式搶奪的則是資料緩衝槽。傳送方要求有空槽可供寫入,而接收方則要求有緩衝資料可讀。需求不符時,同樣加入等待佇列,直到有另一方寫入資料或騰出空槽後被喚醒。

內建函式 cap 和 len 返回緩衝區大小和當前已緩衝數量;而對於同步通道則都返回0,據此可判斷通道是同步還是非同步。

package main

import

"fmt"

func

main()

輸出:

0 03 2

對於 closed 或 nil 通道,傳送和接收操作都有相應規則:

單向通道

儘管可用 make 建立單向通道,但那沒有任何意義。通常使用型別轉換來獲取單向通道,並分別賦予操作雙方。

package main

import

("sync"

)func

main()

}()go

func()

}() wg.

wait()

}

輸出為:01

2同樣, close 不能用於接收端。

package main

func

main()

選擇

如果要同時處理多個通道,可選用 select 語句。它會隨機選擇乙個可用通道做收發操作。

package main

import

"sync"

func

main()

if!ok

println

(name, x)}}

()gofunc()

}}()

wg.wait()

}

輸出:

b 0a 1

b 20

a 3b 40

a 5b 60

b 70

b 80

b 90

如果要等全部通道訊息處理結束,可將已完成通道設定為 nil。這樣它就會被阻塞,不再被 select 選中。

package main

import

"sync"

func

main()

println

("a"

, x)

case x, ok :=

<- b:

if!ok

println

("b"

, x)

}if a ==

nil&& b ==

nil}}(

)gofunc()

}()go

func()

}() wg.

wait()

}

輸出為:

a 0b 0

a 1b 10

a 2b 20

b 30

b 40

同步

將 mutex 作為匿名欄位時,相關方法必須實現為 pointer-receiver,否則會因複製導致鎖機制失效。

package main

import

("sync"

"time"

)type data struct

func

(d data)

test

(s string)}

func

main()

()gofunc()

()wg.

wait()

}

輸出為:

write 0

read 0

write 1

read 1

write 2

read 2

write 3

read 3

read 4

write 4

鎖失效,將 receiver 型別改為 *data 後正常。也可用嵌入 *mutex 來避免複製問題,但那需要專門初始化。

mutex 不支援遞迴鎖,即便在同一 goroutine 下也會導致死鎖。

package main

import

"sync"

func

main()

m.unlock()

}

go 通道 go語言通道channel

通過使用通道,在多個goroutine傳送和接受共享的資料,達到資料同步的目的。通道,他有點像在兩個routine之間架設的管道,乙個goroutine可以往這個管道裡塞資料,另外乙個可以從這個管道裡取資料,有點類似於我們說的佇列。宣告乙個通道很簡單,我們使用chan關鍵字即可,除此之外,還要指定通...

GO 通道的關閉

並不是往通道裡放多少次資料,就必須取多次少資料的 之前的例子都是放3次取3次,放10次取10次 我們可以做乙個操作,當子協程沒有新放入的時候,主協程不再去取,這就是關閉通道 package main import fmt channel並不像檔案那樣需要經常去關閉它,只有當你確實沒有任何傳送資料了,...

Go 緩衝通道

語法結構 cap為容量 ch make chan type,cap 通道是非同步的,是一種在被建立時就被開闢了能儲存乙個或者多個值的通道。這種型別並不要求傳送與接收同時進行。只要緩衝區有未使用空間用於傳送資料,或還包含可以接收的資料,那麼其通訊就會無阻塞地進行。只有在通道中沒有要接收的值時,接收動作...