<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## 概述 - 控制并發有兩種經典的方式,一種是WaitGroup,另外一種就是Context - 用來簡化對于處理單個請求的多個Goroutine之間與請求域的數據、超時和退出等操作 ## Context 使用原則 和 技巧 * 不要把Context放在結構體中,要以參數的方式傳遞,parent Context一般為Background * 應該要把Context作為第一個參數傳遞給入口請求和出口請求鏈路上的每一個函數,放在第一位,變量名建議都統一,如ctx。 * 給一個函數方法傳遞Context的時候,不要傳遞nil,否則在tarce追蹤的時候,就會斷了連接 * Context的Value相關方法應該傳遞必須的數據,不要什么數據都使用這個傳遞 * Context是線程安全的,可以放心的在多個goroutine中傳遞 * 可以把一個 Context 對象傳遞給任意個數的 gorotuine,對它執行 取消 操作時,所有 goroutine 都會接收到取消信號。 * 要養成關閉 Context 的習慣,如果一個 context 被 GC 而不是 cancel 了,那一般是你做錯了 ``` ctx, cancel := context.WithTimeout(parentCtx, time.Second * 2) defer cancel() ``` 結構 ``` type Context func Background() Context func TODO() Context func WithCancel(parent Context) (ctx Context, cancel CancelFunc) func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) func WithValue(parent Context, key, val interface{}) Context ``` ## 實例 ### WithCancel 控制多個 goroutine 實例1 ``` func main() { ctx, cancel := context.WithCancel(context.Background()) go watch(ctx, "【監控1】") go watch(ctx, "【監控2】") go watch(ctx, "【監控3】") time.Sleep(3 * time.Second) fmt.Println("可以了,通知監控停止") cancel() //為了檢測監控過是否停止,如果沒有監控輸出,就表示停止了 time.Sleep(3 * time.Second) } func watch(ctx context.Context, name string) error { for { select { case <-ctx.Done(): fmt.Println(name, "監控退出,停止了...") return ctx.Err() default: fmt.Println(name, "goroutine監控中...") time.Sleep(1 * time.Second) } } } ``` 實例2 ``` func main() { ctx, cancel := context.WithCancel(context.Background()) ch := func(ctx context.Context) <-chan int { ch := make(chan int) go func() { for i := 0; ; i++ { select { case <- ctx.Done(): return case ch <- i: } } } () return ch }(ctx) for v := range ch { fmt.Println(v) if v == 5 { cancel() break } } } ``` ### WithValue用法 ``` func main() { ctx, cancel := context.WithCancel(context.Background()) ctx = context.WithValue(ctx, "name", "cpj") go func(ctx context.Context) { for { select { case <-ctx.Done(): value := ctx.Value("name") println("stop...", value.(string)) return default: println("go...") time.Sleep(1 * time.Second) } } }(ctx) time.Sleep(3 * time.Second) cancel() time.Sleep(3 * time.Second) } ````
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看