Go語言-Context上下文實踐

來源:互聯網
上載者:User

標籤:adl   ini   The   ret   ann   lin   為什麼   rate   contex   

使用 Context 的程式包需要遵循如下的原則來滿足介面的一致性以及便於靜態分析

1.不要把 Context 存在一個結構體當中,顯式地傳入函數。Context 變數需要作為第一個參數使用,一般命名為ctx

2.即使方法允許,也不要傳入一個 nil 的 Context ,如果你不確定你要用什麼 Context 的時候傳一個 context.TODO

3.使用 context 的 Value 相關方法只應該用於在程式和介面中傳遞的和請求相關的中繼資料,不要用它來傳遞一些可選的參數

4.同樣的 Context 可以用來傳遞到不同的 goroutine 中,Context 在多個goroutine 中是安全的

方法說明
  • Done 方法在Context被取消或逾時時返回一個close的channel,close的channel可以作為廣播通知,告訴給context相關的函數要停止當前工作然後返回。

當一個父operation啟動一個goroutine用於子operation,這些子operation不能夠取消父operation。下面描述的WithCancel函數提供一種方式可以取消新建立的Context.

Context可以安全的被多個goroutine使用。開發人員可以把一個Context傳遞給任意多個goroutine然後cancel這個context的時候就能夠通知到所有的goroutine。

  • Err方法返回context為什麼被取消。

  • Deadline返回context何時會逾時。

  • Value返回context相關的資料。
  • context 包已經給我們提供了兩個,一個是 Background(),一個是 TODO(),這兩個函數都會返回一個 Context 的執行個體。只是返回的這兩個執行個體都是空 Context。BackGound是所有Context的root,不能夠被cancel。
執行個體1

這個例子傳遞一個上下文,它有一個任意的截止期,它告訴一個阻塞函數,一旦它到達它,它就應該放棄它的工作。

package mainimport (    "context"    "fmt"    "time")func main() {    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())    }}

運行結果

context deadline exceeded
執行個體2
package mainimport (    "context"    "fmt"    "time")func main() {    d := time.Now().Add(50 * time.Second)    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())    }}

運行結果

overslept
執行個體3
package mainimport (    "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        }    }}

運行結果

12345
執行個體4
package mainimport (    "fmt"    "context")func main() {    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"))}

運行結果

found value: Gokey not found: color
執行個體5
package mainimport (    "fmt"    "context")func main() {    f := func(ctx context.Context, k string) {        if v := ctx.Value(k); v != nil {            fmt.Println("found value:", v)            return        }        fmt.Println("key not found:", k)    }    ctx := context.WithValue(context.Background(), "language", "Go")    f(ctx, "language")    f(ctx, "color")}

運行結果

found value: Gokey not found: color

Go語言-Context上下文實踐

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.