Goでは、チャネルを使用して任意の型の値を送信できます:int、struct、ポインタ、インターフェースなど。
コードと例:
type Data struct { N int } c := make(chan Data) d := Data{N: 1} c <- d // 構造体全体がコピーされる p := &Data{N: 3} c2 := make(chan *Data) c2 <- p // 同じオブジェクトへのポインタがチャネルを通じて送信される
もしチャネルを通じてポインタを持つフィールドを持つ構造体を渡した場合、チャネルの両端でこのフィールドを変更するとレース状態は発生しますか?
回答:
例:
type Box struct { Ptr *int } x := 10 chanBox := make(chan Box) chanBox <- Box{Ptr: &x} // 送信者と受信者の両方がxにアクセスできる!
ストーリー
分散キューで頻繁に「ランダム」なクラッシュとタスク構造内の謎の値が発生しました。調査の結果、チャネルを通じて並行して変更されている共有構造体へのポインタが送信されていることが判明しました。データのコピーでの伝達に変更することにしました。
ストーリー
非同期メッセージ処理は、共通の配列に対するポインタとしてのスライスを内部に持つ構造体で動作していました。一つのメモリの部分をチャネルで並行して送信する際に、異なる場所から変更が加えられ、秘密のバグやデータ損傷を引き起こしました。
ストーリー
プッシュ通知サービスでは、チャネルを通じてオブジェクトへの参照が送信され、ゴルーチンによって処理されました。作業の同時終了とチャネルの閉鎖の際に、一部の構造体がまだ修正されており、パニックまたはデータレースが発生しました。構造体の送信前にコピーに切り替えることで解決しました。