【问题标题】:Golang: How can I stop the execution of a for loop from outside the loop?Golang:如何从循环外停止执行 for 循环?
【发布时间】:2016-06-10 20:01:57
【问题描述】:

我正在使用带有标签的无限 for 循环。在 for 循环的范围之外,我有一个计划函数作为 go 例程运行。当满足某个条件时,我想从预定函数中中断 for 循环。我怎样才能做到这一点?这是我正在尝试的,由于范围问题,这显然行不通。

package main

import (
  "fmt"
  "time"
  "sync"
)

func main() {
  count := 0
  var wg sync.WaitGroup
  wg.Add(1)
  t := time.NewTicker(time.Second*1)

  go func (){
    for {
        fmt.Println("I will print every second", count)
        count++ 
        if count > 5 {
          break myLoop;
          wg.Done()
        }
        <-t.C
    }  
  }()

  i := 1

  myLoop:
  for {
    fmt.Println("iteration", i)
    i++
  }

  wg.Wait()
  fmt.Println("I will execute at the end")

}

【问题讨论】:

标签: go


【解决方案1】:

建立一个信号通道。

quit := make(chan struct{}{})

当你想中断循环时关闭它。

go func (){
    for {
        fmt.Println("I will print every second", count)
        count++ 
        if count > 5 {
          close(quit)
          wg.Done()
          return
        }
        <-t.C
    }  
  }()

在关闭的通道上读取立即返回零值(但在这种情况下我们不需要它)。否则从中读取会阻塞并选择将执行传递给“默认”案例。

 myLoop:
  for {
    select {
    case <- quit:
      break myLoop
    default:
      fmt.Println("iteration", i)
      i++
    }
  }

【讨论】:

    【解决方案2】:

    Darigaaz 的答案适用于单个 goroutine,但关闭关闭的通道会出现恐慌(在这种情况下您也不需要等待组)。如果您有多个 goroutine,并且希望在所有 goroutine 完成后退出循环,请使用具有更接近例程的等待组:

    https://play.golang.org/p/RhmUzWhneT

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    func main() {
        var wg sync.WaitGroup
        quitCh := make(chan struct{})
    
        for i := 1; i <= 5; i++ {
            wg.Add(1)
            go func(i int) {
                count := 1
                t := time.NewTicker(time.Millisecond)
                for count <= 5 {
                    fmt.Printf("Goroutine %v iteration %v\n", i, count)
                    count++
                    <-t.C
                }
                wg.Done()
            }(i)
        }
    
        // This is the closer routine.
        go func() {
            wg.Wait()
            close(quitCh)
        }()
    
        t := time.NewTicker(500 * time.Microsecond)
    loop:
        for i := 1; ; i++ { // this is still infinite
            select {
            case <-quitCh:
                break loop // has to be named, because "break" applies to the select otherwise
            case <-t.C:
                fmt.Println("Main iteration", i)
            }
        }
        fmt.Println("End!")
    
    }
    

    作为命名循环样式的替代方案,您可以在该选择中使用fallthrough break:

        for i := 1; ; i++ { // this is still infinite
            select {
            case <-quitCh:
                // fallthrough
            case <-t.C:
                fmt.Println("Main iteration", i)
                continue
            }
            break // only reached if the quitCh case happens
        }
    

    【讨论】:

      猜你喜欢
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多