go如何终止多个for select循环嵌套

发布时间:2024年01月12日

?空山新雨后,天气晚来秋。

目录

分类说明

总结


分类说明

for select循环嵌套,如何终止?上代码:

?? ?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:

已关闭 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

换成先终止内层也可:

?? ?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:

已关闭 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

如果不是基于关闭操作而是写入呢,内层和外层都能收到吗? 答:只会接收一次。

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 即可达到其下嵌套的所有该循环的目的。

文章来源:https://blog.csdn.net/HYZX_9987/article/details/135543917
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。