代码如下:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Second)
ctx, cancel := context.WithCancel(context.Background())
TickerHandle(ticker, ctx)
time.Sleep(3 * time.Second)
cancel()
}
func TickerHandle(ticker *time.Ticker, ctx context.Context) {
go func() {
defer func() {
ticker.Stop()
fmt.Println("Defer Ticker Stop!")
}()
for {
select {
case <-ctx.Done():
fmt.Println("Ticker Stop1")
return
case <-ticker.C:
fmt.Println("Ticker...")
}
}
fmt.Println("Ticker Stop2")
}()
}
执行结果1:
Ticker...
Ticker...
执行结果2:
Ticker...
Ticker...
Ticker...
Ticker Stop1
Defer Ticker Stop!
执行结果3:
Ticker....
Ticker....
Ticker....
Ticker Stop1
执行结果4:
Ticker...
Ticker...
Ticker...
尝试在go1.12~1.16中执行,每次执行结果是不确定的,所以使用context.WithCancel()这种方式是没有办法真正使执行ticker的goroutine停止退出,需要使用channel。
主要是这里有个疑惑,为什么多次执行每次执行结果都不是确定的?
main里面的cancel()执行后,main就退出了,此时整个程序也就退出,所以其他协程可能还没来得及执行相关程序也随着main的退出而退出了