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

 更新时间:2024年01月12日 11:22:54   作者:ProblemTerminator  
当您想从嵌套循环中中断,从select内部终止循环时,标记的中断非常有用,本文主要介绍了go如何终止多个for select循环嵌套的方法,具有一定的参考价值,感兴趣的可以了解一下

分类说明

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

到此这篇关于go如何终止多个for select循环嵌套的方法的文章就介绍到这了,更多相关go 终止循环嵌套内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • RabbitMq如何做到消息的可靠性投递

    RabbitMq如何做到消息的可靠性投递

    现在的一些互联网项目或者是高并发的项目中很少有没有引入消息队列的。 引入消息队列可以给这个项目带来很多的好处,这篇文章主要为大家介绍了RabbitMq如何做到消息的可靠性投递,有需要的朋友可以借鉴参考下
    2022-12-12
  • golang使用os/exec库查询进程方式

    golang使用os/exec库查询进程方式

    本文介绍了使用Go语言os/exec查询进程的方法,并提供了两种方式,第一种方式输出了当前系统所有运行的进程,第二种方式可以过滤出指定进程的信息
    2026-04-04
  • Go语言与其他语言进行交互的方式详解

    Go语言与其他语言进行交互的方式详解

    在当今的软件开发领域,多种编程语言常常需要协同工作,以充分利用各自的优势来构建复杂的应用系统,Go 语言作为一门高效、简洁的编程语言,也经常需要与其他语言进行交互,接下来,我们将详细探讨 Go 语言如何与其他语言进行交互,需要的朋友可以参考下
    2024-06-06
  • 一文详解go的defer和return的执行顺序

    一文详解go的defer和return的执行顺序

    go的defer和return是golang中的两个关键字,return用于返回函数的返回值,也可以参与一定的流程控制,defer是golang中的延迟调用,经常用于文件流的关闭,锁的解锁操作,本文给大家介绍了go的defer和return的执行顺序,需要的朋友可以参考下
    2024-07-07
  • go处理线程之间的交互示例代码

    go处理线程之间的交互示例代码

    Go语言以goroutine为核心实现并发编程,其中线程间交互主要通过Channels、WaitGroup、Mutex和Select实现,Channels提供goroutine间的数据传递,本文给大家介绍go处理线程之间的交互示例代码,感兴趣的朋友一起看看吧
    2024-10-10
  • Go语言实现Viper配置管理笔记

    Go语言实现Viper配置管理笔记

    Viper 是一个功能强大、灵活易用的配置管理工具,本文主要介绍了Go语言实现Viper配置管理笔记,具有一定的参考价值,感兴趣的可以了解一下
    2025-04-04
  • Go的固定时长定时器和周期性时长定时器

    Go的固定时长定时器和周期性时长定时器

    本文主要介绍了Go的固定时长定时器和周期性时长定时器,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Go log模块的使用技巧

    Go log模块的使用技巧

    Golog模块是一个强大的日志记录库,提供了丰富的功能,如线程安全的日志记录、灵活的日志格式配置、多种输出目标支持等,它还提供了错误处理和程序终止功能,以及自定义Logger的创建,本文给大家介绍Go log模块的使用,感兴趣的朋友一起看看吧
    2025-11-11
  • 完美解决golang go get私有仓库的问题

    完美解决golang go get私有仓库的问题

    这篇文章主要介绍了完美解决golang go get私有仓库的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • Go语言微服务中实现链路追踪

    Go语言微服务中实现链路追踪

    在微服务架构中,链路追踪技术可以帮助我们跟踪请求在各个服务之间的传播路径,本文就来介绍一下Go语言微服务中实现链路追踪,感兴趣的可以了解一下
    2024-12-12

最新评论