WithCancel实例:
package main
import (
"context"
"fmt"
)
/*
Context 包定义了上下文类型,该上下文类型跨越 API 边界和进程之间传递截止期限,取消信号和其他请求范围值。
对服务器的传入请求应创建一个 Context,对服务器的传出调用应接受 Context。它们之间的函数调用链必须传播 Context,可以用使用 WithCancel,WithDeadline,WithTimeout 或WithValue创建的派生上下文替换。当 Context 被取消时,从它派生的所有 Context 也被取消。
WithCancel,WithDeadline 和 WithTimeout 函数采用Context(父级)并返回派生的Context(子级)和CancelFunc。调用 CancelFunc 将取消子对象及其子对象,删除父对子对象的引用,并停止任何关联的定时器。未能调用CancelFunc 会泄漏子项及其子项,直至父项被取消或计时器激发。go vet 工具检查在所有控制流路径上使用 CancelFuncs。
使用 Contexts 的程序应该遵循这些规则来保持包之间的接口一致,并使静态分析工具能够检查上下文传播:
不要将上下文存储在结构类型中;相反,将一个 Context 明确地传递给每个需要它的函数。上下文应该是第一个参数,通常命名为 ctx
*/
func main() {
// Create a new cancellable context from a new blank context.
//
// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
//
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
ctx, cancel := context.WithCancel(context.Background())
// Even though ctx should have been cancelled already, 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()
// Create a new message channel.
msg := make(chan string)
// Call fnc 10 times in their own goroutines.
for i := 0; i < 10; i++ {
go fnc(i, msg, ctx, cancel)
}
// Receive and print a single message from the msg channel.
fmt.Println(<-msg)
// Wait until the cotext is cancelled before exiting main.
<-ctx.Done()
}
// fnc takes in an integer, message string channel, a context and also a cancel function
// for that context.
func fnc(i int, msg chan string, ctx context.Context, cancel context.CancelFunc) {
select {
// Check if the context was already cancelled.
//
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
// expires; WithTimeout arranges for Done to be closed when the timeout
// elapses.
case <-ctx.Done():
fmt.Printf("fnc %d cancelled\n", i)
return
// Send a string on the msg channel and then cancel the context so the
// other goroutines exit cleanly.
case msg <- fmt.Sprintf("fnc %d finished first\n", i):
cancel()
}
}
package main
import