4

でコンソール音楽プレーヤーに取り組んでいGoます。ユーザーがアルバムを選択して再生するたびに、ゴルーチンを起動してプレイリストをループします。

playlist := make([]*Media, 0)
for _, path := range album.Paths {
    media, err := NewMediaFromPath(path)
    // return err

    playlist = append(playlist, media)
}

for idx := range playlist {
    player.SetMedia(playlist[idx])
    err = player.Play()
    // check err

    status, err := player.MediaState()
    // check err

    for status != MediaEnded && status != MediaStopped {
        // update UI and check player status
        // loop until the song finishes
        status, err = player.MediaState()
    }
}

ユーザーが新しいアルバムを選択したときに、このゴルーチンをキャンセルする方法が必要です。私はそうしています(しかし、それが最善の解決策であるとは確信していません)。context.Context

私はctx

    ctx, cancel := context.WithCancel(context.Background())

したがって、UI イベント ハンドラーでplay() funccancel()、ゴルーチンになります。

これは、更新 UIforループ内をチェックすると機能します。

        select {
        case <-ctx.Done():
            return err
        default:
            time.Sleep(50 * time.Millisecond)
        }

その後、チャンネルctx.Done()が閉じられ、再生される次のアルバムがループの代わりに常に返されます。

キャンセルする方法はありcontext.Contextますか?

そうでない場合、このゴルーチン (および次のゴルーチン) をキャンセルするより良い方法はありますか?

別の方法として、待機グループを使用しようとしましたが、

    go func() {
        wg.Wait()
        wg.Add(1)
        err = playAlbum(
            done,
            player,
            *albums[s],
            list,
            status,
        )
        wg.Done()
        // handle err
     }()

でもsync: WaitGroup is reused before previous Wait has returnedそのうちパニックになる

4

1 に答える 1