Counter
を定義しましょう。Inc
を呼び出すたびにインクリメントする必要がありますCounter
を中心にさらに多くのテストを作成するので、テストが少し明確に読み取れるように、小さなアサーション関数assertCount
を作成します。wantedCount
をループし、goroutineを起動して、counter.Inc()
を呼び出します。WaitGroup
は、ゴルーチンのコレクションが完了するのを待ちます。メインのゴルーチンはAdd
を呼び出して、待機するゴルーチンの数を設定します。次に、各ゴルーチンが実行され、完了したらDone
を呼び出します。同時に、すべてのゴルーチンが完了するまで、Wait
を使用してブロックすることができます。
wg.Wait()
が完了するのを待つことで、すべてのゴルーチンがCounter
をInc
しようとしたことを確認できます。Mutex
は相互排他ロックです。ミューテックスのゼロ値は、ロックされていないミューテックスです。
Inc
を呼び出すgoroutineが最初にある場合、Counter
のロックを取得することです。他のすべてのゴルーチンは、アクセスを取得する前に、それがUnlock
されるのを待つ必要があります。sync.Mutex
が構造体に埋め込まれている他の例を見てきました。Lock
とUnlock
を公開することはせいぜい混乱を招きますが、最悪の場合、同じタイプの呼び出し元がこれらのメソッドの呼び出しを開始すると、ソフトウェアに非常に有害な可能性があります。mutexes
のコピーgo vet
を実行すると、次のようなエラーが表示されますミューテックスは、最初の使用後にコピーしてはなりません。
Counter
(by value)をassertCounter
に渡すと、ミューテックスのコピーが作成されます。Counter
へのポインターを渡す必要があるため、assertCounter
のシグネチャを変更します*Counter
ではなくCounter
を渡そうとしているため、テストはコンパイルされなくなりました。これを解決するには、自分で型を初期化しない方がよいことをAPIのリーダーに示すコンストラクタを作成することをお勧めします。Counter
を初期化するときに、この関数をテストで使用します。Mutex
を使用すると、データにロックを追加できますWaitgroup
は、ゴルーチンがジョブを完了するのを待つ手段ですGoの初心者によくある間違いは、それが可能であったり、楽しいからといって、チャネルやゴルーチンを使いすぎてしまうことです。sync.Mutex
が問題に最も適している場合は、恐れずに同期を使用してください。 Goは、問題を最もよく解決するツールを使用できるようにし、1つのスタイルのコードに強制するのではなく、実用的です。
go vet
を使用することを忘れないでください。貧弱なユーザーに影響が及ぶ前に、コード内のいくつかの微妙なバグを警告することができます。