成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go1.21 速覽:Context 可以設置取消原因和回調函數了,等的可太久了!

開發 前端
Context 一直是大家使用的最頻繁的標準庫之一,他聯通了整個 Go 里的工程體系。這次在 Go1.21 對 Context 增加了 WithXXXCause 相關函數的錯誤類型支持。對于我們在 Go 工程實踐中的排查和定位,能夠有一些不錯的助力。

大家好,我是煎魚。

在 Go 中有一個很經典的設計:context,這是許多同學初學時必學的標準庫。涉及到上下文傳遞、超時控制等必要項。

甚至在函數體中的第一個參數大多是傳 context。寫第三方庫也必須兼容 context 設置,否則會經常有人提需求讓你支持。

我覺得這次的新特性更新雖不復雜,但作用挺大。建議大家學習!

Context Demo

以下是一個快速 Demo:

package main

import (
 "context"
 "fmt"
 "time"
)

const shortDuration = 1 * time.Millisecond

func main() {
 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())
 }

}

運行結果:

context deadline exceeded

一切都看起來沒什么問題。

麻煩點

但在實際寫業務代碼和排查問題時,你就會發現一個麻煩的事。在出現上下文超時或到達所設置的截止時間時,ctx.Err 方法可以獲得 context deadline exceeded 的錯誤信息。

但這是遠遠不夠的,你只知道是因為誘發了超時。但不知道是哪里導致的,還得再去根據訪問的邏輯,再走一遍腦洞,再進行排查。又或是根據代碼堆棧,再去設想,最后復現成功。

又或是查不到。因為這種一般是偶現,很有可能就留給下一代的繼承者了~

又更有業務訴求,希望在出現上下文的異常場景時,可以及時執行回調方法。然而這沒有太便捷的實現方式。

Go1.21 增強 Context

增加 WithXXXCause

在即將發布的 Go1.21,針對 Context 的錯誤處理終于有了一點點的增強,來填補這個地方的信息,允許添加自定義的錯誤類型和信息。

新增的 Context API 如下:

// WithDeadlineCause behaves like WithDeadline but also sets the cause of the
// returned Context when the deadline is exceeded. The returned CancelFunc does
// not set the cause.
func WithDeadlineCause(parent Context, d time.Time, cause error) (Context, CancelFunc)

// WithTimeoutCause behaves like WithTimeout but also sets the cause of the
// returned Context when the timout expires. The returned CancelFunc does
// not set the cause.
func WithTimeoutCause(parent Context, timeout time.Duration, cause error) (Context, CancelFunc)

與原先的 WithDeadline 和 WithTimeout 作用基本一致,唯一區別就是在形參上增加了 cause error,允許傳入錯誤類型。

WithTimeoutCause

WithTimeoutCause 的使用示例:

tooSlow := fmt.Errorf("too slow!")
ctx, cancel := context.WithTimeoutCause(context.Background(), 1*time.Second, tooSlow)
time.Sleep(2*time.Second)
cancel()

像上述程序,執行 ctx.Err 方法時得到的結果是:context.DeadlineExceeded,這是既有的。

此時,我們再結合在 Go1.20 版本加入的 context.Cause 方法:

func Cause(c Context) error

就能得到對應的錯誤信息,上述的結果對應的是 tooSlow 變量。

WithCancelCause

WithCancelCause 的使用示例,計時器先觸發:

finishedEarly := fmt.Errorf("finished early")
tooSlow := fmt.Errorf("too slow!")
ctx, cancel := context.WithCancelCause(context.Background())
ctx, _ = context.WithTimeoutCause(ctx, 1*time.Second, tooSlow)
time.Sleep(2*time.Second) // timer fires, setting the cause
cancel(finishedEarly) // no effect as ctx has already been canceled

對應的程序結果:

  • ctx.Err():context.DeadlineExceeded 類型。
  • context.Cause(ctx):tooSlow 類型。

先發生上下文取消的使用示例:

finishedEarly := fmt.Errorf("finished early")
tooSlow := fmt.Errorf("too slow!")
ctx, cancel := context.WithCancelCause(context.Background())
ctx, _ = context.WithTimeoutCause(ctx, 1*time.Second, tooSlow)
time.Sleep(500*time.Millisecond) // timer hasn't expired yet
cancel(finishedEarly) // cancels the timer and sets ctx.Err()

對應的程序結果:

  • ctx.Err():context.Canceled 類型。
  • context.Cause(ctx):finishedEarly 類型。

增加 AfterFunc

同樣的,在 Go1.21 也對 Context(上下文)被取消的動作后增加了一些增強。平時當上下文被取消時,我們只能通過啟動 Goroutine 來監視取消行為并做一系列操作。

但這未免繁瑣且增大了我們的編碼和運行成本,因為每次處理都要 goroutine+select+channel 來一套組合拳,才能真正到寫自己業務代碼的地方。

為此新版本增加了注冊函數的功能,將會在上下文被取消時調用。函數簽名如下:

func AfterFunc(ctx Context, f func()) (stop func() bool)

在函數作用上,該函數會在 ctx 完成(取消或超時)后調用所傳入的函數 f。

在運行機制上,它會自己在 goroutine 中調用 f。需要注意的是,即使 ctx 已經完成,調用 AfterFunc 也不會等待 f 返回。

這也是可以套娃的,在 AfterFunc 里再套 AfterFunc。這里用不好也很容易 goroutine 泄露。

基于這個新函數,可以看看以下兩個例子作為使用場景。

1、多 Context 合并取消的例子:

func WithFirstCancel(ctx1, ctx2 context.Context) (context.Context, context.CancelFunc) {
 ctx, cancel := context.WithCancel(ctx1)
 stopf := context.AfterFunc(ctx2, func() {
  cancel()
 })
 return ctx, func() {
  cancel()
  stopf()
 }
}

2、在取消上下文時停止等待 sync.Cond:

func Wait(ctx context.Context, cond *sync.Cond) error {
 stopf := context.AfterFunc(ctx, cond.Broadcast)
 defer stopf()
 cond.Wait()
 return ctx.Err()
}

基本滿足了各種上下文的復雜訴求了。

總結

Context 一直是大家使用的最頻繁的標準庫之一,他聯通了整個 Go 里的工程體系。這次在 Go1.21 對 Context 增加了 WithXXXCause 相關函數的錯誤類型支持。對于我們在 Go 工程實踐中的排查和定位,能夠有一些不錯的助力。

另外 AfterFunc 函數的增加,看起來是個簡單的功能。但是可以解決以往的一些合并取消上下文和串聯處理的復雜場景,是一個不錯的擴展功能。

苛刻些,美中不足的就是,Go 都已經發布 10+ 年了,加的還是有些太晚了。同時針對 Context 也需要有更體系的排查和定位側的補全了。

責任編輯:武曉燕 來源: 腦子進煎魚了
相關推薦

2023-06-07 10:32:57

內置函數clear

2023-06-19 08:49:55

go文件管理

2023-05-05 08:51:18

Go語言泛型

2023-07-05 08:47:24

Go版本團隊

2018-04-09 14:26:06

Go語法實踐

2023-08-09 08:53:50

GoWASI語義

2025-01-14 11:01:38

2012-02-01 10:33:59

Java

2023-08-02 08:46:02

Go版本號規則

2011-06-15 11:05:14

C語言回調函數

2011-10-31 14:04:40

Windows XP

2023-04-18 08:10:10

2025-05-20 08:20:00

GoGo Context上下文

2011-05-20 17:59:06

回調函數

2025-05-06 00:00:08

2023-11-10 16:31:31

2022-12-09 08:52:51

Go匿名接口

2019-11-05 10:03:08

callback回調函數javascript

2022-04-12 08:30:52

回調函數代碼調試

2011-07-25 14:32:40

Cocoa 框架 函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产综合久久久久久丝袜 | www视频在线观看 | 每日在线更新av | 亚洲国产精品久久人人爱 | 国产精品毛片久久久久久久 | avav在线看| 欧美日韩综合一区 | 久久国产精品视频 | 精品一区二区三区四区 | 中文字幕视频在线观看 | 欧美一级毛片在线播放 | 国产精品色| 国产一区二区三区在线 | 天天操操操操操 | 日韩精品一区二区三区在线观看 | 青娱乐一区二区 | jlzzxxxx18hd护士| 日韩免费视频一区二区 | 国产精品免费一区二区三区四区 | 国产精品一区二区无线 | 欧美日韩在线一区二区三区 | 成人黄色a | 亚洲一区| 日韩在线免费视频 | 免费成人在线网 | xxx国产精品视频 | 久久亚洲国产精品 | 青草青草久热精品视频在线观看 | 亚洲精品区 | 国产又色又爽又黄又免费 | 午夜成人免费视频 | 亚洲第一区久久 | 日韩福利一区 | 久久伊人一区二区 | 狠狠爱一区二区三区 | 成人天堂噜噜噜 | 精品久久久久久 | 99国内精品 | 中文字幕一区在线观看视频 | 国产视频精品视频 | 久久久久成人精品亚洲国产 |