Тикер Остановить поведение в Голанге
Если я перемещаюсь по каналу тикера и остановке вызова(), канал останавливается, но не закрывается.
В этом примере:
package main
import (
"time"
"log"
)
func main() {
ticker := time.NewTicker(1 * time.Second)
go func(){
for _ = range ticker.C {
log.Println("tick")
}
log.Println("stopped")
}()
time.Sleep(3 * time.Second)
log.Println("stopping ticker")
ticker.Stop()
time.Sleep(3 * time.Second)
}
Запуск производит:
2013/07/22 14:26:53 tick
2013/07/22 14:26:54 tick
2013/07/22 14:26:55 tick
2013/07/22 14:26:55 stopping ticker
Так что горутин никогда не выходит. Есть ли лучший способ справиться с этим делом? Должен ли я беспокоиться, что горутин никогда не выходил?
Ответы
Ответ 1
Сигнал "сделанный" на втором канале и выберите в вашем канате между тикером и записанным каналом.
В зависимости от того, что вы действительно хотите сделать, лучшее решение может существовать, но это трудно сказать из приведенного демо-кода.
Ответ 2
Используется второй канал, как предложил Фолькер. Это то, с чем я закончил работу:
package main
import (
"log"
"time"
)
// Run the function every tick
// Return false from the func to stop the ticker
func Every(duration time.Duration, work func(time.Time) bool) chan bool {
ticker := time.NewTicker(duration)
stop := make(chan bool, 1)
go func() {
defer log.Println("ticker stopped")
for {
select {
case time := <-ticker.C:
if !work(time) {
stop <- true
}
case <-stop:
return
}
}
}()
return stop
}
func main() {
stop := Every(1*time.Second, func(time.Time) bool {
log.Println("tick")
return true
})
time.Sleep(3 * time.Second)
log.Println("stopping ticker")
stop <- true
time.Sleep(3 * time.Second)
}
Ответ 3
вы можете сделать это.
package main
import (
"fmt"
"time"
)
func startTicker(f func()) chan bool {
done := make(chan bool, 1)
go func() {
ticker := time.NewTicker(time.Second * 1)
defer ticker.Stop()
for {
select {
case <-ticker.C:
f()
case <-done:
fmt.Println("done")
return
}
}
}()
return done
}
func main() {
done := startTicker(func() {
fmt.Println("tick...")
})
time.Sleep(5 * time.Second)
close(done)
time.Sleep(5 * time.Second)
}
Ответ 4
Если вам нужно сохранить больше каналов использования пространства пустых структур - struct {}, которые не требуют памяти. И, как уже упоминалось выше, don.t отправляет что-то в нем - просто закрывается, что фактически посылает нулевое значение.