I have a function that is launched as a goroutine:
func (bt *BlinkyTape) finiteLoop(frames []Frame, repeat int, delay time.Duration) {
bt.isPlaying = true
L:
for i := 0; i < repeat; i++ {
select {
case <-bt.stop:
break L
default:
bt.playFrames(frames, delay)
}
}
bt.isPlaying = false
}
This function uses channels so it is possible to break the loop (loop can be finite or infinite)
What I would like to implement is a way to pause the execution of the loop and of course being able to resume it.
I was thinking to add another case to the select condition where I listen on another channel pause
. If the case is executed, it enter in a new infinite loop that does nothing. Then it will need the same system as previously with a resume
channel to break this loop.
What do you think ? Is there a better way to achieve what I need ?
Regards
Pause a loop in a goroutine with channels, use play
, pause
and quit
channels like this working sample code:
package main
import "fmt"
import "time"
import "sync"
func routine() {
for {
select {
case <-pause:
fmt.Println("pause")
select {
case <-play:
fmt.Println("play")
case <-quit:
wg.Done()
return
}
case <-quit:
wg.Done()
return
default:
work()
}
}
}
func main() {
wg.Add(1)
go routine()
time.Sleep(1 * time.Second)
pause <- struct{}{}
time.Sleep(1 * time.Second)
play <- struct{}{}
time.Sleep(1 * time.Second)
pause <- struct{}{}
time.Sleep(1 * time.Second)
play <- struct{}{}
time.Sleep(1 * time.Second)
close(quit)
wg.Wait()
fmt.Println("done")
}
func work() {
time.Sleep(250 * time.Millisecond)
i++
fmt.Println(i)
}
var play = make(chan struct{})
var pause = make(chan struct{})
var quit = make(chan struct{})
var wg sync.WaitGroup
var i = 0
output:
1
2
3
4
pause
play
5
6
7
8
pause
play
9
10
11
12
done