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