我正在开发控制台音乐播放器Go
。每当用户选择并播放专辑时,我都会启动一个 goroutine来循环播放列表。
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()
}
}
当用户选择新专辑时,我需要一种取消此 goroutine的方法。我习惯这样做(但我不相信这是最好的解决方案)。context.Context
我创建ctx
ctx, cancel := context.WithCancel(context.Background())
所以在 UI 事件处理程序中,play()
func
将cancel()
goroutine。
一旦我检查更新 UIfor
循环,这就会起作用:
select {
case <-ctx.Done():
return err
default:
time.Sleep(50 * time.Millisecond)
}
然后通道ctx.Done()
关闭,下一张播放的专辑将始终返回而不是循环播放。
有没有办法取消a context.Context
?
如果没有,有没有更好的方法来取消这个 goroutine(以及以下 goroutines)?
或者,我尝试使用等待组,
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
恐慌