2016-06-09 358 views
0

我正在使用带有标签的无限循环。在for循环的范围之外,我有一个按照例行程序运行的预定函数。当某个条件满足时,我想打破预定函数的for循环。我怎样才能做到这一点?这是我正在尝试的,由于范围问题,这显然不起作用。Golang:我如何停止从循环外执行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") 

} 
+8

你看过Go频道吗? – Nadh

+2

这是基本的围棋并发,一个良好的开端可能会在[围棋之旅并发章(https://tour.golang.org/concurrency/1) – JimB

+1

使用通过阅读转到博客取消管道:HTTPS ://blog.golang.org/pipelines – eduncan911

回答

3

建立信令信道。

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++ 
    } 
    } 
4

Darigaaz的回答适用于单一的goroutine,但收盘封闭通道恐慌(而你也不必在实例中waitgroup)。如果您有多个够程,并希望循环退出所有的人都完成之后,使用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!") 

} 

作为替代到指定的循环风格,可以而是使用该选择中的突破性突破:

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 
    }