1.原代码如下
package main
import (
"fmt"
"time"
)
func main() {
intchan := make(chan int,1)
ticker := time.NewTicker(time.Second)
go func() {
for range ticker.C{ //每隔1s执行一次
select {
case intchan <- 1:
case intchan <- 2:
case intchan <- 3:
}
}
fmt.Println("End.[sender]")
}()
var sum int
for e:= range intchan{
fmt.Printf("received:%v\n",e)
sum += e
if sum>=5{
fmt.Printf("got:%v\n",sum)
break
}
}
fmt.Println("end.[receiver]")
}
2.修改代码:在接收方暂停断续器ticker.stop
- 在接收方加入ticker.Stop()代码,暂停断续器,查看是否能打印输出End.[sender]
package main
import (
"fmt"
"time"
)
func main() {
intchan := make(chan int,1)
ticker := time.NewTicker(time.Second)
go func() {
for range ticker.C{
select {
case intchan <- 1:
case intchan <- 2:
case intchan <- 3:
}
}
fmt.Println("End.[sender]")
}()
var sum int
for e:= range intchan{
fmt.Printf("received:%v\n",e)
sum += e
if sum>=5{
fmt.Printf("got:%v\n",sum)
ticker.Stop()
break
}
}
//time.Sleep(time.Second*2)
// 测试用,当主goroutine休眠了1s仍然无法输出End.[sender]
fmt.Println("end.[receiver]")
}
- 当和大于5时,暂停断续器,仍然无法打印输出End.[sender],即使主goroutine休眠1s
- 解释:ticker的stop方法,该方法会停止计时,意味着不会向定时器的管道中写入事件,但管道并不会关闭。管道只有在使用完成后,声明周期结束后才会自动释放。
- 即使停止了断续器,循环卡在循环range ticker.C,无法继续向下执行,所以无法打出End.[sender]
3.修改代码:添加一个stopchan管道
- 添加一个stopchan管道,当主goroutine中sum大于等于5时,满足条件,向stopchan中传入数据。因为stopchan原先无数据,在select中无法执行该case,处于阻塞状态,当得到数据后,便会执行该case,执行其中代码
package main
import (
"fmt"
"time"
)
func main() {
intchan := make(chan int,1)
stopchan := make(chan bool)
ticker := time.NewTicker(time.Second)
go func() {
for range ticker.C{
select {
case intchan<-1:
case intchan<-2:
case intchan<-3:
case stop:=<-stopchan:
if stop{
ticker.Stop()
fmt.Println("End.[sender]")
}
}
}
fmt.Println("End.[sender]")
}()
var sum int
for e:= range intchan{
fmt.Printf("received:%v\n",e)
sum += e
if sum>=5{
fmt.Printf("got:%v\n",sum)
stopchan <- true
break
}
}
fmt.Println("end.[receiver]")
}
received:1
received:3
received:2
got:6
End.[sender]
end.[receiver]