Golang:如何从循环外部停止执行for循环?

时间:2016-06-09 15:01:52

标签: go

我正在使用带标签的无限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")

}

2 个答案:

答案 0 :(得分:4)

建立信号通道。

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
    }  
  }()

读取封闭通道立即返回零值(但在这种情况下我们不需要它)。否则从中读取块并选择将执行传递给&#34;默认&#34;情况下。

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

答案 1 :(得分:4)

Darigaaz的答案适用于单个goroutine,但关闭一个封闭的频道恐慌(并且在该实例中你也不需要等待组)。如果你有多个goroutine,并希望循环在所有循环完成后退出,请使用一个具有更近程序的waitgroup:

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中断:

    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
    }