2017-01-14 01:05:42 +01:00
|
|
|
// Copyright 2016 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package context_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// This example demonstrates the use of a cancelable context to prevent a
|
|
|
|
// goroutine leak. By the end of the example function, the goroutine started
|
|
|
|
// by gen will return without leaking.
|
|
|
|
func ExampleWithCancel() {
|
|
|
|
// gen generates integers in a separate goroutine and
|
|
|
|
// sends them to the returned channel.
|
|
|
|
// The callers of gen need to cancel the context once
|
|
|
|
// they are done consuming generated integers not to leak
|
|
|
|
// the internal goroutine started by gen.
|
|
|
|
gen := func(ctx context.Context) <-chan int {
|
|
|
|
dst := make(chan int)
|
|
|
|
n := 1
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return // returning not to leak the goroutine
|
|
|
|
case dst <- n:
|
|
|
|
n++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return dst
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel() // cancel when we are finished consuming integers
|
|
|
|
|
|
|
|
for n := range gen(ctx) {
|
|
|
|
fmt.Println(n)
|
|
|
|
if n == 5 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Output:
|
|
|
|
// 1
|
|
|
|
// 2
|
|
|
|
// 3
|
|
|
|
// 4
|
|
|
|
// 5
|
|
|
|
}
|
|
|
|
|
2018-01-09 02:23:08 +01:00
|
|
|
// This example passes a context with an arbitrary deadline to tell a blocking
|
2017-01-14 01:05:42 +01:00
|
|
|
// function that it should abandon its work as soon as it gets to it.
|
|
|
|
func ExampleWithDeadline() {
|
|
|
|
d := time.Now().Add(50 * time.Millisecond)
|
|
|
|
ctx, cancel := context.WithDeadline(context.Background(), d)
|
|
|
|
|
|
|
|
// Even though ctx will be expired, it is good practice to call its
|
|
|
|
// cancelation function in any case. Failure to do so may keep the
|
|
|
|
// context and its parent alive longer than necessary.
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-time.After(1 * time.Second):
|
|
|
|
fmt.Println("overslept")
|
|
|
|
case <-ctx.Done():
|
|
|
|
fmt.Println(ctx.Err())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output:
|
|
|
|
// context deadline exceeded
|
|
|
|
}
|
|
|
|
|
|
|
|
// This example passes a context with a timeout to tell a blocking function that
|
|
|
|
// it should abandon its work after the timeout elapses.
|
|
|
|
func ExampleWithTimeout() {
|
|
|
|
// Pass a context with a timeout to tell a blocking function that it
|
|
|
|
// should abandon its work after the timeout elapses.
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-time.After(1 * time.Second):
|
|
|
|
fmt.Println("overslept")
|
|
|
|
case <-ctx.Done():
|
|
|
|
fmt.Println(ctx.Err()) // prints "context deadline exceeded"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output:
|
|
|
|
// context deadline exceeded
|
|
|
|
}
|
|
|
|
|
2018-09-24 23:46:21 +02:00
|
|
|
// This example demonstrates how a value can be passed to the context
|
|
|
|
// and also how to retrieve it if it exists.
|
2017-01-14 01:05:42 +01:00
|
|
|
func ExampleWithValue() {
|
|
|
|
type favContextKey string
|
|
|
|
|
|
|
|
f := func(ctx context.Context, k favContextKey) {
|
|
|
|
if v := ctx.Value(k); v != nil {
|
|
|
|
fmt.Println("found value:", v)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
fmt.Println("key not found:", k)
|
|
|
|
}
|
|
|
|
|
|
|
|
k := favContextKey("language")
|
|
|
|
ctx := context.WithValue(context.Background(), k, "Go")
|
|
|
|
|
|
|
|
f(ctx, k)
|
|
|
|
f(ctx, favContextKey("color"))
|
|
|
|
|
|
|
|
// Output:
|
|
|
|
// found value: Go
|
|
|
|
// key not found: color
|
|
|
|
}
|