1// Copyright 2016 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package context_test 6 7import ( 8 "context" 9 "fmt" 10 "time" 11) 12 13const shortDuration = 1 * time.Millisecond // a reasonable duration to block in an example 14 15// This example demonstrates the use of a cancelable context to prevent a 16// goroutine leak. By the end of the example function, the goroutine started 17// by gen will return without leaking. 18func ExampleWithCancel() { 19 // gen generates integers in a separate goroutine and 20 // sends them to the returned channel. 21 // The callers of gen need to cancel the context once 22 // they are done consuming generated integers not to leak 23 // the internal goroutine started by gen. 24 gen := func(ctx context.Context) <-chan int { 25 dst := make(chan int) 26 n := 1 27 go func() { 28 for { 29 select { 30 case <-ctx.Done(): 31 return // returning not to leak the goroutine 32 case dst <- n: 33 n++ 34 } 35 } 36 }() 37 return dst 38 } 39 40 ctx, cancel := context.WithCancel(context.Background()) 41 defer cancel() // cancel when we are finished consuming integers 42 43 for n := range gen(ctx) { 44 fmt.Println(n) 45 if n == 5 { 46 break 47 } 48 } 49 // Output: 50 // 1 51 // 2 52 // 3 53 // 4 54 // 5 55} 56 57// This example passes a context with an arbitrary deadline to tell a blocking 58// function that it should abandon its work as soon as it gets to it. 59func ExampleWithDeadline() { 60 d := time.Now().Add(shortDuration) 61 ctx, cancel := context.WithDeadline(context.Background(), d) 62 63 // Even though ctx will be expired, it is good practice to call its 64 // cancellation function in any case. Failure to do so may keep the 65 // context and its parent alive longer than necessary. 66 defer cancel() 67 68 select { 69 case <-time.After(1 * time.Second): 70 fmt.Println("overslept") 71 case <-ctx.Done(): 72 fmt.Println(ctx.Err()) 73 } 74 75 // Output: 76 // context deadline exceeded 77} 78 79// This example passes a context with a timeout to tell a blocking function that 80// it should abandon its work after the timeout elapses. 81func ExampleWithTimeout() { 82 // Pass a context with a timeout to tell a blocking function that it 83 // should abandon its work after the timeout elapses. 84 ctx, cancel := context.WithTimeout(context.Background(), shortDuration) 85 defer cancel() 86 87 select { 88 case <-time.After(1 * time.Second): 89 fmt.Println("overslept") 90 case <-ctx.Done(): 91 fmt.Println(ctx.Err()) // prints "context deadline exceeded" 92 } 93 94 // Output: 95 // context deadline exceeded 96} 97 98// This example demonstrates how a value can be passed to the context 99// and also how to retrieve it if it exists. 100func ExampleWithValue() { 101 type favContextKey string 102 103 f := func(ctx context.Context, k favContextKey) { 104 if v := ctx.Value(k); v != nil { 105 fmt.Println("found value:", v) 106 return 107 } 108 fmt.Println("key not found:", k) 109 } 110 111 k := favContextKey("language") 112 ctx := context.WithValue(context.Background(), k, "Go") 113 114 f(ctx, k) 115 f(ctx, favContextKey("color")) 116 117 // Output: 118 // found value: Go 119 // key not found: color 120} 121