Ticker 中的那个通道怎么关闭呢?

```go func main() { done := make(chan bool) ticker := time.NewTicker(time.Millisecond * 500) go func() { for t := range ticker.C { fmt.Println("Tick at", t) } fmt.Println("done<-true") //这个好象执行不到!!所以死锁了?? done <- true }() time.Sleep(time.Millisecond * 1600) ticker.Stop() //close(ticker.C) 这句编译不过 fmt.Println("Ticker stopped") <-done } ``` 查了下文档,说ticker.Stop()不会关闭那个通道。但手动用close以不能关,原因是cannot close receive-only channel,这个如何是好?
已邀请:

stevewang

赞同来自: gameogre

加一个channel作为控制开关就可以了。

另外,其实ticker可以放在goroutine里,goroutine结束时执行stop,这样代码结构更好一些。

```go
package main

import (
"fmt"
"time"
)

func main() {

done := make(chan bool)
closed := make(chan struct{}, 1)
go func() {
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
LOOP:
for {
select {
case t := <-ticker.C:
fmt.Println("Tick at", t)
case <-closed:
break LOOP
}
}
done <- true
}()

time.Sleep(time.Millisecond * 1600)
closed <- struct{}{}
<-done
fmt.Println("Ticker stopped")
}
```

boilingbit

赞同来自: gameogre

据说要go v2才会考虑,见
https://codereview.appspot.com/5491059

gameogre - 游戏魔兽

```go
func startTimer(f func()) chan struct{} {
done := make(chan struct{}, 1)
go func() {
timer := time.NewTicker(5 * time.Minute)
defer timer.Stop()
for {
select {
case <-timer.C:
f()
case <-done:
return
}
}
}()
return done
}
// 使用方法
done := startTimer(a.authenticate)
...
close(done)
```

搜到的,确实巧妙,把关闭的这个事件绕开了,值得学习。但是,不考虑解决方案的问题,只说这个通道如何关闭,有什么办法吗?还是说一旦碰到需要关闭通道这个问题的话,是不是就意味着用法有问题了?不能以 for .. range 的形式使用这个Ticker的channel ?

谢谢。

要回复问题请先登录注册