go筆記-理解幾種Context
阿新 • • 發佈:2020-12-14
WithCancel
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
WithCancel返回一個新的parent拷貝Done channel。當呼叫返回的cancel函式
或parent的上下文的Done channel被關閉
時(以先發生的為準),將關閉返回的上下文的Done channel。
取消此上下文將釋放與其關聯的資源,因此在此上下文中執行的操作完成後,程式碼應立即呼叫cancel。
示例
此示例演示了使用可取消的context來防止goroutine洩漏。 在示例函式結束時,由gen方法啟動的goroutine將返回而不會洩漏。
package main import ( "context" "fmt" ) func main() { // 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 } } }
WithDeadline
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
WithTimeout內部呼叫了WithDeadline,返回結果為WithDeadline(parent, time.Now().Add(timeout)).
取消此上下文將釋放與之關聯的資源,因此在此上下文中執行的操作完成後,程式碼應立即呼叫cancel:
示例
此示例傳遞了帶有超時的上下文,以告知阻塞函式在超時結束後應放棄任務。
package main import ( "context" "fmt" "time" ) const shortDuration = 1 * time.Millisecond func main() { // 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(), shortDuration) defer cancel() select { case <-time.After(1 * time.Second): fmt.Println("overslept") case <-ctx.Done(): fmt.Println(ctx.Err()) // prints "context deadline exceeded" } } // 執行後1ms立刻輸出 "context deadline exceeded"
示例2
package main
import (
"context"
"fmt"
"time"
)
const shortDuration = 500 * time.Millisecond
func work(ctx context.Context, doneChan chan struct{}) {
defer func() {
fmt.Println("work end")
}()
fmt.Println("work start")
time.Sleep(100 * time.Second)
fmt.Println("work finished")
doneChan <- struct{}{}
}
func main() {
doneChan := make(chan struct{}, 1)
dlCtx, cancel := context.WithTimeout(context.Background(), shortDuration)
defer func() {
cancel()
fmt.Println("cancel")
}()
fmt.Println("main start")
go work(dlCtx, doneChan)
select{
case <- dlCtx.Done():
fmt.Println("timeout")
case <- doneChan:
fmt.Println("finish")
}
fmt.Println("main end")
}
輸出:
main start
work start
timeout
main end
cancel
WithTimeout
WithValue