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