2017-09-24 76 views
3

预计:待后大约完成。 2秒方面取消不退出

实际:无限期地运行。

不明白这可能是导致其无限期投放。

package main 

import (
    "context" 
    "fmt" 
    "time" 
) 

func main() { 
    ctx, cancel := context.WithCancel(context.Background()) 
    defer cancel() 

    for i := range generator(ctx) { 
     select { 
     case <-time.After(2 * time.Second): 
      cancel() 
      return 
     default: 
      fmt.Println(i) 
     } 
    } 
} 

func generator(ctx context.Context) <-chan int { 
    ch := make(chan int) 

    go func() { 
     count := 0 
     for { 
      select { 
      case <-ctx.Done(): 
       return 
      case ch <- count: 
       count++ 
      } 
     } 
    }() 

    return ch 
} 

回答

4

的主要问题是,你的频道从generator(ctx)发出返回值几乎一样快,您可以阅读它们。

通过time.After(2 * time.Second)创建的通道几乎立即丢弃,并创建一个新的超时通道通过发电机每次迭代。

如果你让一个小的变化;创建超时通道外部的循环,然后将其放入select子句中,您将看到它开始工作。

timeout := time.After(2 * time.Second) 
for i := range generator(ctx) { 
    select { 
    case <-timeout: 
     cancel() 
     return 
    default: 
     fmt.Println(i) 
    } 
} 

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

+0

谢谢。对我来说多么愚蠢的小姐! – technologyblogger

+1

顺便说一下,这相当于'context.WithTimeout(context.Background(),2 * time.Second)'(并且没有显式定时器)。 – Peter

+0

不错的加法@Peter –