首先报错
fatal error: all goroutines are asleep - deadlock!
这说明主协程被阻塞,同时所有其他协程也阻塞或者退出,即没有在工作中的协程
package main
import (
"context"
"log"
)
func main() { //主协程1
c, cancel := context.WithCancel(context.Background())
defer cancel()
ch1 := make(chan int)
go func() { //协程2
for {
ch1 <- 2
// fmt.Println(1111)
}
}()
Start2(ch1, c) //协程3
ch1 <- 1
ch1 <- 2
}
// 会一直轮训执行select channel 且无法用break 退出循环
func Start1(c1 chan int, c context.Context) {
go func() {
for {
select {
case <-c.Done():
log.Println("event manager done!")
return
case val, ok := <-c1:
if !ok {
log.Println("event channel unexpectedly closed")
return
}
log.Println("val:", val)
}
}
}()
}
// select 外面没有for 则挑选到符合条件的channel 执行一次便退出
func Start2(c1 chan int, c context.Context) {
go func() {
select {
case <-c.Done():
log.Println("event manager done!")
return
case val, ok := <-c1:
if !ok {
log.Println("event channel unexpectedly closed")
return
}
log.Println("val:", val)
}
}()
}
由于start2没有for, 执行一次协程3便退出了,主协程和协程2都在阻塞向channel中发送数据,因此没有协程在工作了,因此会报死锁错误
将协程2里换成语句2,虽然主协程还在阻塞,但可以正常运行,因为协程2在工作
package main
import (
"context"
"log"
)
func main() { //主协程1
c, cancel := context.WithCancel(context.Background())
defer cancel()
ch1 := make(chan int)
go func() { //协程2
for {
ch1 <- 2 //语句1
// fmt.Println(1111) //语句2
}
}()
Start1(ch1, c)
ch1 <- 1
ch1 <- 2
}
// 会一直轮训执行select channel 且无法用break 退出循环
func Start1(c1 chan int, c context.Context) {
go func() {
for {
select {
case <-c.Done():
log.Println("event manager done!")
return
case val, ok := <-c1:
if !ok {
log.Println("event channel unexpectedly closed")
return
}
log.Println("val:", val)
}
}
}()
}
// select 外面没有for 则挑选到符合条件的channel 执行一次便退出
func Start2(c1 chan int, c context.Context) {
go func() {
select {
case <-c.Done():
log.Println("event manager done!")
return
case val, ok := <-c1:
if !ok {
log.Println("event channel unexpectedly closed")
return
}
log.Println("val:", val)
}
}()
}
用start2则不管协程2里是语句1还是语句2,程序都会正常运行,因为start2在不断地从channel里消费数据
通过start1和start2的对比可以看出,select + 多个case 只会选择一个符合条件的 channel 去执行,且只执行一次并退出,
要连续处理多个数据,必须外层用for循环,且这个for循环无法用break退出,必须用 return 退出函数
网友评论