Go Context介紹

context包是Go 語言中用來設(shè)置截止日期慕购、同步信號震桶,傳遞請求相關(guān)值的結(jié)構(gòu)體,是開發(fā)常用的并發(fā)控制技術(shù)毫蚓。
WaitGroup的不同在于context可以控制多級的goroutine占键。

1. 接口定義

type Context interface {
    Deadline()  (deadline time.Time, ok bool)
    
    Done() <- chan struct{}

    Err() error

    Value(key interface{}) interface{}
}

Deadline(): 工作的截止時間,沒有設(shè)置deadlineok==false元潘。
Done(): 需要在select-case語句中使用(case <-context.Done(): )畔乙。當(dāng)context被關(guān)閉后,Done()返回一個被關(guān)閉的通道(關(guān)閉的通道依然是可以讀的翩概,所以goroutine可以收到關(guān)閉請求)牲距;當(dāng)context還未關(guān)閉時,Done()返回nil钥庇。
Err(): 描述context關(guān)閉的原因牍鞠,其原因由context實現(xiàn)控制。例如:因deadline關(guān)閉:context deadline exceeded评姨;因主動關(guān)閉:context canceled难述。沒有關(guān)閉時,返回nil吐句。
Value(): 特別的用于一種context:不用于控制呈樹狀分布的goroutine胁后,而是用于在樹狀分布的goroutine之間傳遞信息。Value()方法根據(jù)key值查詢map中的Value嗦枢。

2. 使用

一個案例來展示context的使用攀芯,它做了2件事:1. 創(chuàng)建過期時間為1s的上下文。 2. 將context傳入handle函數(shù)中净宵,函數(shù)使用500ms的時間處理請求敲才。

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
    defer cancel()

    go handle(ctx, 500*time.Millisecond)
    select {
    case <-ctx.Done():
        fmt.Println("main", ctx.Err())
    }
}

func handle(ctx context.Context, duration time.Duration) {
    select {
    case <-ctx.Done():
        fmt.Println("handle", ctx.Err())
    case <-time.After(duration):
        fmt.Println("process request with", duration)
    }
}

output:

process request with 500ms
main context deadline exceeded

分析: context過期時間為1s裹纳,處理時間為0.5秒(select中的過期時間),函數(shù)有足夠的時間完成處理紧武,也就是<-time.After(duration):會在<-ctx.Done()之前完成剃氧,故輸出process request with 500ms。再過0.5s阻星,<-ctx.Done()完成朋鞍,這時候輸出main context deadline exceeded

倘若妥箕,代碼中的``改為400*time.Millisecond滥酥,會輸出什么呢?
A:

main context deadline exceeded

B:

main context deadline exceeded
handle context deadline exceeded

C:

process request with 500ms
main context deadline exceeded

D:

process request with 500ms

E:

handle context deadline exceeded
main context deadline exceeded

答案是:A畦幢、B坎吻、E
可能出現(xiàn)這3種,而不是1種的原因是和調(diào)度器有關(guān)宇葱。


context的一些方法

  • 默認(rèn)上下文: 以下兩個方法都會返回預(yù)先初始化好的私有變量 backgroundtodo瘦真,它們會在同一個 Go 程序中被復(fù)用。這兩個私有變量都是通過 new(emptyCtx) 語句初始化的黍瞧,它們是指向私有結(jié)構(gòu)體 context.emptyCtx的指針诸尽,這是最簡單、最常用的上下文類型印颤。
    • context.Background(): 是上下文的默認(rèn)值您机,所有其他的上下文都應(yīng)該從它衍生出來。
    • context.TODO(): 應(yīng)該僅在不確定應(yīng)該使用哪種上下文時使用年局。
  • 取消信號:前兩個創(chuàng)建的是context.WithCancel际看,最后一個創(chuàng)建的是context.timerCtx
    • context.WithCancel(): 由context.Context()衍生出的特殊的子上下文某宪。一旦它的返回函數(shù)被執(zhí)行仿村,其所有子context將都會被返回。
    • context.WithDeadline(): 在某個時間點進(jìn)行返回兴喂。
    • context.WithTimeout(): 某個時間段過后進(jìn)行返回蔼囊。
  • 傳值方法
    • context.WithValue(): 從父上下文中創(chuàng)建一個子上下文,傳值的子上下文使用 context.valueCtx衣迷。
      需要注意的是這個方法是遞歸的根據(jù)Key來獲取Value的畏鼓。
func (c *valueCtx) Value(key interface{}) interface{} {
    if c.key == key {
        return c.val
    }
    return c.Context.Value(key)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市壶谒,隨后出現(xiàn)的幾起案子云矫,更是在濱河造成了極大的恐慌,老刑警劉巖汗菜,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件让禀,死亡現(xiàn)場離奇詭異挑社,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)巡揍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門痛阻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人腮敌,你說我怎么就攤上這事阱当。” “怎么了糜工?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵弊添,是天一觀的道長。 經(jīng)常有香客問我捌木,道長油坝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任刨裆,我火速辦了婚禮免钻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘崔拥。我一直安慰自己,他們只是感情好凤覆,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布链瓦。 她就那樣靜靜地躺著,像睡著了一般盯桦。 火紅的嫁衣襯著肌膚如雪慈俯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天拥峦,我揣著相機(jī)與錄音贴膘,去河邊找鬼。 笑死略号,一個胖子當(dāng)著我的面吹牛刑峡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播玄柠,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼突梦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了羽利?” 一聲冷哼從身側(cè)響起宫患,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎这弧,沒想到半個月后娃闲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虚汛,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年皇帮,在試婚紗的時候發(fā)現(xiàn)自己被綠了卷哩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡玲献,死狀恐怖殉疼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捌年,我是刑警寧澤瓢娜,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站礼预,受9級特大地震影響眠砾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜托酸,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一褒颈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧励堡,春花似錦谷丸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鹅龄,卻和暖如春揩慕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扮休。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工迎卤, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玷坠。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓蜗搔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親侨糟。 傳聞我的和親對象是個殘疾皇子碍扔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Go context 在RPC或者Web服務(wù)中,當(dāng)Server端接受一個request的時候秕重,都會開啟一個額外的g...
    qingshuiting閱讀 8,727評論 0 2
  • Go標(biāo)準(zhǔn)庫Context 在 Go http包的Server中不同,每一個請求在都有一個對應(yīng)的 goroutine 去...
    吳佳浩閱讀 370評論 0 2
  • Context 通常被譯作上下文,一般理解為程序單元的一個運行狀態(tài)、現(xiàn)場二拐、快照服鹅,而翻譯中上下文又很好地詮釋了它的本...
    Asphalt7閱讀 546評論 0 0
  • 控制并發(fā)有兩種經(jīng)典的方式:WaitGroup和Context WaitGroup:控制多個Goroutine同時完...
    JunChow520閱讀 664評論 0 2
  • 1 什么是Context 最近在公司分析gRPC源碼,proto文件生成的代碼百新,接口函數(shù)第一個參數(shù)統(tǒng)一是ctx c...
    淘小鋪刀仔閱讀 321評論 0 1