Если этот код является лишь шаблоном задачи с собеседования, который предполагалось расширить, то можно добавить условную переменную и обычную переменную для текущего счетчика:
package main
import (
"fmt"
"sync"
)
func main() {
wg := &sync.WaitGroup{}
ch := make(chan string)
mu := sync.Mutex{}
s := 0
c := sync.NewCond(&mu)
for i := 0; i < 5; i++ {
wg.Add(1)
go func(group *sync.WaitGroup, i int) {
defer group.Done()
mu.Lock() // c.L.Lock()
for s != i {
c.Wait()
}
ch <- fmt.Sprintf("Goroutine %d", i)
s += 1
c.Broadcast()
mu.Unlock() // c.L.Unlock()
}(wg, i)
}
c.Broadcast()
for i := 0; i < 5; i++ {
select {
case s := <-ch:
fmt.Println(s)
}
}
wg.Wait()
}