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

関連する問題