GOチャンネル詳細

5845 ワード

ChannelはGoのコアタイプで、パイプと見なし、コアユニットを並列に接続することでデータを送信または受信して通信することができます.
オペレータは矢印です
ch 

(矢印の向きはデータの流れです)
mapとsliceのデータ型のように、channelはまず作成してから使用する必要があります.
ch := make(chan int)

チャネルタイプ


Channelタイプの定義形式は次のとおりです.
ChannelType = ( "chan" | "chan" "

3つのタイプの定義が含まれています.オプション
chan T          //   T  
chan
chan

makeを使用してチャネルを初期化し、容量を設定します.
make(chan int, 100)

容量(capacity)は、チャネルが格納する最も多くの要素の数を表し、チャネルのキャッシュのサイズを表します.容量が設定されていない場合、または容量が0に設定されている場合は、チャネルにキャッシュがないことを示し、senderとreceiverが準備されている場合にのみ、それらの通信(communication)が発生します.キャッシュが設定されている場合、ブロックは発生しない可能性があります.bufferがいっぱいになるとsendがブロックされ、キャッシュが空になるとreceiveがブロックされます.nil channelは通信しません.
チャンネルを閉じるには、組み込まれたcloseメソッドを使用します.
複数のgoroutineで1つのchannelからreceive/sendデータを1つのchannelに転送することができ、追加の同期措置を考慮する必要はありません.
チャネルは、受信されたデータと送信されたデータの順序が一致する、先入先出(FIFO)のキューとして機能することができる.
channelのreceiveはmulti-valued assignmentをサポートします.たとえば、次のようにします.
v, ok := 

チャンネルが閉じられているかどうかを確認するために使用できます.
send文send文は、chの定義のように、往復チャンネルでデータを送信する.
SendStmt = Channel "

通信(communication)が開始される前にchannelとexpressionは必ず値を求めて(evaluated)、例えば以下の(3+4)は7を計算してからchannelに送信します.
c := make(chan int)
defer close(c)
go func() { c 

sendが実行される前に通信(communication)がブロックされていた.前述したように、キャッシュされていないchannelはreceiverが準備された後にsendが実行されるのみです.キャッシュがあり、キャッシュが満たされていない場合はsendが実行されます.
closeされたchannelにデータを送信し続けるとrun-time panicになります.
nil channelへの送信データは一致してブロックされます.
receiveオペレータは、nil channelからデータを受信するとblockされます.
closeされたchannelからの受信データはブロックされず、直ちに返され、送信されたデータを受信すると要素タイプのゼロ値(zero value)が返されます.
前述したように、channelがオフになっているかどうかを確認するために、追加の戻りパラメータを使用することができます.
x, ok := 

OKがfalseである場合、受信したxが生成されたゼロ値であることを示し、このchannelは閉じられているか、空である.

blocking


デフォルトでは、送信と受信は、他方が準備できるまでブロックされます.この方法は、表示されたロックや条件変数を使用することなくgororutineで同期するために使用することができる.
公式の例ではx,y:=
import "fmt"
func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c 

Buffered Channels


makeの2番目のパラメータは、キャッシュのサイズを指定します: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 

range cで生成された反復値はチャネルで送信された値であり、チャネルが閉じられるまで反復される.上記の例ではclose(c)を注釈すると、プログラムはfor......rangeの行にブロックされ続けます.

select


select文は、可能なsend操作とreceive操作のセットを選択して処理します.switchに似ていますが、通信(communication)操作を処理するために使用されます.そのcaseはsend文であってもよいし、receive文であってもよいし、defaultであってもよい.
receive文は、1つまたは2つの変数に値を割り当てることができます.receive操作でなければなりません.
最大1つのdefault caseを許可します.caseリストの任意の場所に置くことができますが、ほとんどは最後に置きます.
import "fmt"
func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c 

同時に複数のcaseが処理され、例えば同時に複数のchannelがデータを受信できる場合、Goは1つのcase処理(pseudo-random)を擬似ランダムに選択する.caseが処理する必要がない場合はdefaultを選択し、default caseが存在する場合はdefaultを選択します.default caseがない場合、select文はcaseが処理する必要があるまでブロックされます.
注意すべきは、nil channelの操作は常にブロックされ、default caseがなければ、nil channelのselectだけがブロックされます.
select文はswitch文と同様にループではなくcaseを選択して処理します.channelをずっと処理したい場合は、無限のforループを外部に追加できます.
for {
    select {
    case c 

timeout


selectの重要な応用の一つはタイムアウト処理である.上で述べたように、caseが処理する必要がなければ、select文はずっとブロックされています.この場合、タイムアウトを処理するためにタイムアウト操作が必要になる可能性があります.次の例では、2秒後にchannel c 1にデータを送信しますが、selectは1秒タイムアウトに設定されているので、result 1ではなくtimeout 1を印刷します.
import "time"
import "fmt"
func main() {
    c1 := make(chan string, 1)
    go func() {
        time.Sleep(time.Second * 2)
        c1 

実はtimeを利用していますAfterメソッドは、次のタイプを返します.

TimerとTicker


時間について2つのチャンネルを見てみましょう.timerはタイマーで、未来の単一イベントを代表して、timerにどのくらい待つかを教えて、それはチャネルを提供して、将来のその時間にそのチャネルは時間値を提供します.次の例では、2行目は2秒程度の時間をブロックし、時間になってから実行を続行します.
timer1 := time.NewTimer(time.Second * 2)

もちろん、単純に待ちたいだけならtimeを使ってもいいです.Sleepが実現します.
timerも使えますストップしてタイマーを止めます.
timer2 := time.NewTimer(time.Second)
go func() {
    

tickerは、1つの間隔(interval)でチャネルにイベント(現在の時間)を送信し、チャネルの受信者は一定の時間間隔でチャネルからイベントを読み出すことができるタイミングトリガタイマである.次の例では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を閉じるために使用できます.
チャネルが閉じたsenderのreceiver操作をまとめます.チャネルcが閉じられている場合、データを送信し続けるとpanic:send on closedチャネル:
import "time"
func main() {
    go func() {
        time.Sleep(time.Hour)
    }()
    c := make(chan int, 10)
    c 

しかし、この閉じたchannelからは、送信されたデータだけでなく、ゼロ値も絶えず読み出すことができます.
c := make(chan int, 10)
c 

ただしrangeで読み込むと、channelがオフになるとforループが飛び出します
c := make(chan int, 10)
c 

i,ok:=
c := make(chan int, 10)
close(c)
i, ok := 

同期


channelはgoroutine間の同期に使用できます.次の例ではmain goroutineがdone channelを介してworkerがタスクを完了するのを待つ.workerがタスクを完了したらchannelにデータを送信するだけでmain goroutineタスクの完了を通知できます.
import (
    "fmt"
    "time"
)
func worker(done chan bool) {
    time.Sleep(time.Second)
    //  
    done 

変換元:https://colobu.com/2016/04/14/Golang-Channels/