空山新雨后,天气晚来秋。
目录
分类说明
for select循环嵌套,如何终止?上代码:
Go
stop := make(chan struct{})
go func() {
for i := 1; i < 3; i++ {
fmt.Println("writed ", i)
time.Sleep(time.Second * 1)
}
close(stop)
fmt.Println("stop closed.")
}()
go func() {
stop1:
for {
select {
case <-stop:
fmt.Println("recv 1")
break stop1
default:
fmt.Println("A 1 default...")
for {
select {
case <-stop:
fmt.Println("recv 2")
break stop1
default:
fmt.Println("A 2 default...")
time.Sleep(time.Second * 1)
}
}
}
}
fmt.Println("A 结束")
}()
fmt.Println("已关闭", stop == nil)
for i := 1; i < 10; i++ {
time.Sleep(time.Second * 1)
fmt.Println("ch==nil: ", stop == nil, " num=", runtime.NumGoroutine())
}
如上,内外均监听了stop,内层接受到信号后直接终止stop1,全流程正常结束。效果如下:
speed running:
Go
已关闭 false
A 1 default...
A 2 default...
writed 1
A 2 default...
writed 2
ch==nil: false num= 3
ch==nil: false num= 3
A 2 default...
stop closed.
recv 2
A 结束
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
换成先终止内层也可:
Go
stop := make(chan struct{})
go func() {
for i := 1; i < 3; i++ {
fmt.Println("writed ", i)
time.Sleep(time.Second * 1)
}
close(stop)
fmt.Println("stop closed.")
}()
go func() {
stop1:
for {
select {
case <-stop: // 这里也可收到信号
fmt.Println("recv 1")
break stop1
default:
fmt.Println("A 1 default...")
stop2:
for {
select {
case <-stop: // 这里可收到信号
fmt.Println("recv 2")
break stop2 // 换成终止内层
default:
fmt.Println("A 2 default...")
time.Sleep(time.Second * 1)
}
}
fmt.Println("A 2 stop...")
}
}
fmt.Println("A 结束")
}()
fmt.Println("已关闭", stop == nil)
for i := 1; i < 10; i++ {
time.Sleep(time.Second * 1)
fmt.Println("ch==nil: ", stop == nil, " num=", runtime.NumGoroutine())
}
如上代码,在内层先终止自己的逻辑stop2,外层也随之终止,正常结束。效果如下:
speed running:
Go
已关闭 false
writed 1
A 1 default...
A 2 default...
writed 2
ch==nil: false num= 3
A 2 default...
A 2 default...
ch==nil: false num= 3
stop closed.
recv 2
A 2 stop...
recv 1
A 结束
ch==nil: false num= 2
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
ch==nil: false num= 1
如果不是基于关闭操作而是写入呢,内层和外层都能收到吗? 答:只会接收一次。
Go
stop := make(chan struct{})
go func() {
for i := 1; i < 3; i++ {
//ch <- i
fmt.Println("writed ", i)
time.Sleep(time.Second * 1)
}
stop <- struct{}{}// close(stop)
fmt.Println("stop writed.")
}()
go func() {
stop1:
for {
select {
case <-stop: // 这里未收到信号
fmt.Println("recv 1")
break stop1
//case data := <-ch:
// fmt.Println("A data=", data)
default:
fmt.Println("A 1 default...")
stop2:
for {
select {
case <-stop: // 这里可收到信号
fmt.Println("recv 2")
break stop2 // 换成终止内层
default:
fmt.Println("A 2 default...")
time.Sleep(time.Second * 1)
}
}
fmt.Println("A 2 stop...")
}
}
fmt.Println("A 结束")
}()
fmt.Println("stop == nil: ", stop == nil)
for i := 1; i < 10; i++ {
time.Sleep(time.Second * 1)
fmt.Println("ch==nil: ", stop == nil, " num=", runtime.NumGoroutine())
}
close(stop)
fmt.Println("stop已关闭, ", stop == nil)
speed running:
stop == nil: false
writed 1
A 1 default...
A 2 default...
A 2 default...
writed 2
ch==nil: false num= 3
recv 2
A 2 stop...
A 1 default...
A 2 default...
stop writed.
ch==nil: false num= 3
ch==nil: false num= 2
A 2 default...
A 2 default...
ch==nil: false num= 2
ch==nil: false num= 2
A 2 default...
A 2 default...
ch==nil: false num= 2
A 2 default...
ch==nil: false num= 2
ch==nil: false num= 2
A 2 default...
A 2 default...
ch==nil: false num= 2
stop已关闭, false
总结
触发条件需要全部结束时,直接终止最外层for select 即可达到其下嵌套的所有该循环的目的。