Go コルーチンの一般的なエラーには次のものがあります。 コルーチン リーク: リソースの不適切な解放による過剰なメモリ消費。解決策: defer ステートメントを使用します。デッドロック: 複数のコルーチンがループ内で待機します。解決策: ループ待機モードを回避し、アクセスを調整するためにチャネルまたは sync.Mutex を使用します。データ競合: 共有データは複数のコルーチンによって同時にアクセスされます。解決策: sync.Mutex または sync.WaitGroup を使用して共有データを保護します。タイマーのキャンセル: コルーチンがキャンセルされた後、タイマーが正しくキャンセルされません。解決策: context.Context を使用してキャンセル信号を伝達します。
Go プログラミングにおいて、コルーチン (ゴルーチンとも呼ばれます) は、同時アプリケーションの開発に役立つ軽量のスレッドです。コルーチンは非常に便利ですが、使用方法を誤ると問題を引き起こす可能性もあります。このガイドでは、Go コルーチンのよくある間違いと落とし穴を調査し、それらを回避するためのベスト プラクティスを提供します。
問題: コルーチンが期待どおりに終了しない場合、コルーチン リークが発生する可能性があります。これによりメモリ消費量が増加し、最終的にはアプリケーションがクラッシュする可能性があります。
解決策: defer
ステートメントを使用して、コルーチンが戻ったときにコルーチン内のリソースが正しく解放されるようにします。
func example1() { defer wg.Done() // 确保等待组 wg 在例程返回时减 1 // ... 其他代码 }
問題: 2 つ以上のコルーチンが互いの完了を待機すると、デッドロックが発生します。たとえば、次のコードでは、コルーチン A はコルーチン B が完了するまで待機し、コルーチン B はコルーチン A が完了するまで待機します。
func example2() { ch1 := make(chan struct{}) ch2 := make(chan struct{}) go func() { <-ch1 // 等待协程 B ch2 <- struct{}{} // 向协程 B 发送信号 }() go func() { ch1 <- struct{}{} // 向协程 A 发送信号 <-ch2 // 等待协程 A }() }
解決策: 複数のコルーチン間での実行を避ける ループを作成する待つパターン。代わりに、チャネルまたは sync.Mutex
を使用して共有リソースへのアクセスを調整することを検討してください。
問題:複数のコルーチンが共有可変データに同時にアクセスすると、データ競合が発生する可能性があります。これにより、データの破損や予期しない動作が発生する可能性があります。
解決策: sync.Mutex
や sync.WaitGroup
などの同期メカニズムを使用して、共有データを同時アクセスから保護します。
var mu sync.Mutex func example3() { mu.Lock() // ... 访问共享数据 mu.Unlock() }
問題:コルーチンがキャンセルされると、タイマーが正しくキャンセルされない場合があります。これにより、不必要なリソースの消費が発生し、アプリケーションがクラッシュする可能性もあります。
解決策: context.Context
を使用してキャンセル信号を伝播し、タイマーがこのコンテキストで開始されるようにします。
func example4(ctx context.Context) { timer := time.NewTimer(time.Second) defer timer.Stop() // 当 ctx 被取消时停止计时器 select { case <-timer.C: // 定时器已触发 case <-ctx.Done(): // 计时器已被取消 } }
以下は、上記のベスト プラクティスを使用してコルーチン リークの問題を解決する例です。
func boundedGoroutinePool(n int) { var wg sync.WaitGroup ch := make(chan task, n) for i := 0; i < n; i++ { go func() { for task := range ch { wg.Add(1) go func() { defer wg.Done() task.Do() }() } }() } // ... 提交任务 close(ch) wg.Wait() }
待機グループを使用する (sync) .WaitGroup
) を使用して実行中のコルーチンを追跡すると、送信されたすべてのタスクが完了する前にコルーチン プールが終了しないことを保証できるため、コルーチンのリークを回避できます。
以上がGolang コルーチンのよくある間違いと落とし穴の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。