2017-09-24 77 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 –