golang channel & select

1922 ワード

メッセージを通じてデータを共有することはgolangの設計哲学であり、channelはこのような哲理の体現である.チャンネル定義
var varName chan dataType

DataTypeは非常に広く、基本的なstring、intなどであってもよいし、map、slice、カスタムtypeタイプであってもよいし、channelであってもよい.タイプが豊富なため、golangではメッセージでデータを共有することが容易です.
初期化
channelはmakeによって初期化される.未初期化のchannelはnilである(未初期化によるデッドロックの問題に接触することが多い).channelは矢印でbuffer sizeが0または欠落している場合、unbufferedと呼ぶ.逆にbuffered channelである.
ブロックじょうけん
  • 初期化されていないchannelは、
  • をブロックし続けます.
  • unbuffered channel:読み書きと同時に準備ができていると、channelは通信を開始し、読み書きだけがブロックされます.
  • buffered channelにデータを書くと、書き終わるまでブロックされ、読みはchannelが空になるまでブロックされます.

  • bufferを持たないchannelは順序実行、同期などを実現しやすい.buffer付きchannelは通常非同期イベントを処理するために使用され、中に投げ込むと撤退する.
    チャンネルを閉じる
    closeでchannelを閉じることができますが、close後、中のデータはすべて消費されるまで存在します.ただ、リソースを解放する場所があります.close channel後、len(channel)で残りのリソースを判断し、対応する処理を行います.ところで、ここにはもう一つの細部があります.
    v,ok := 

    チャンネルが閉鎖されたかどうかを上記のように判断するところが多い.実はこの言い方は小さな穴を持っています.buffer channel、close()後、中にデータが入っていれば、上のような方法でデータを取ることができますが、okもtrueですが、いつ取得できませんか?それは中のデータが全部消費された後、okはfalseです.したがって、上記の式は、以下のようにより合理的に記述されています.
    v,ok:=
    よく使われることがありますが、初心者が不思議に思うのは、
    chan 

    空のデータをchannelに渡すという意味です.struct{}{}はメモリが非常に小さいため、データの内容にも関心がなく、通常、あるサービスを終了するなど、信号量として処理するために使用される.
    select
    式:
    select{
    case :
    /*...*/
    default:
    /*...*/
    }
    

    通常、複数のチャンネルを処理する必要がある場所で用いられる.selectは、あるcaseがメッセージを受信するまで渋滞するが、default caseがある場合、他のcaseがメッセージを受信していない場合は、すぐにdefault caseに進み、select文全体が終了する.
    for ... select
    通常for...select文はメッセージをループ処理するために、2つの点に少し注意する必要がある.1.breakはselect文に用いることができるので、break文ではforループ全体を中断することはできない.ではforループから飛び出したいのはどうしますか?ラベル:
    LOOP:
        for{
            select{
                case ....:
                    break LOOP  //@A
            }
          }
    
        @A   
    

    2.select文はブロックされている、すなわち、選択したcaseが実行するまで次のループに進む.従って、時間がかかることは中に入れないで、単独でgo routineを開いて処理することができる.