Go context
在RPC或者Web服務(wù)中,當(dāng)Server端接受一個(gè)request的時(shí)候罢荡,都會(huì)開啟一個(gè)額外的gorountine來處理內(nèi)容叔锐。有時(shí)候可能會(huì)使用多個(gè)gorountine來處理同一個(gè)request芋哭。如果對(duì)應(yīng)的request被取消或者timeout,就需要所有為這個(gè)request服務(wù)的gorountine被快速回收睬隶。
context解釋更多的是一種上下文
基本方法
-
初始化方法
TODO
Background
-
多種類型的context
WithCancel
WithDeadline
WithTimeout
WithValue
deadline和timeout可以通過使用cancel和timer實(shí)現(xiàn)
context接口內(nèi)容
Deadline:返回deadline锣夹,表明對(duì)應(yīng)的context對(duì)應(yīng)的工作需要被cancel。如果返回的ok是false苏潜,那么表明就沒有設(shè)置deadline時(shí)間银萍。
-
Done:返回一個(gè)channel,當(dāng)work做完以后這個(gè)channel就會(huì)被關(guān)閉窖贤。當(dāng)對(duì)應(yīng)的context被cancel了就會(huì)返回一個(gè)chan砖顷。
如果done返回是nil表明表明這個(gè)context是不能夠被cancel的。withcancel赃梧,withdeadline滤蝠,withtimeout都有對(duì)應(yīng)的Done的操作。因?yàn)镈one會(huì)返回一個(gè)read chan授嘀,可以用于判斷對(duì)應(yīng)的context是否被cancel物咳,來控制流程。// func Stream(ctx context.Context, out chan<- Value) error { // for { // v, err := DoSomething(ctx) // if err != nil { // return err // } // select { // case <-ctx.Done(): // return ctx.Err() // case out <- v: // } // } // }
-
Err
如果Done沒有被close蹄皱,那么Err返回的都是nil
如果Done已經(jīng)執(zhí)行了close览闰,那么Err返回的是非nil,返回的Error類型可以根據(jù)具體的情況判斷巷折。就是兩種压鉴,一種是cancel另一個(gè)匯總deadlineExceeded。
-
Value
返回與context的key關(guān)聯(lián)的value
使用方法
context的使用一般都是按照層次性的锻拘,這個(gè)層次指的是gorountine的層次油吭。因?yàn)橛锌赡芪覀兪褂枚鄠€(gè)gorountine或者更深層次的gorountine來處理一個(gè)request击蹲。
一般使用的根節(jié)點(diǎn)都是直接使用context.Background
后邊可以與WithCancel,DeadLine婉宰,TimeOut配合使用歌豺。Parent context可以通過cancel fun等來控制其子context的結(jié)束(也對(duì)應(yīng)著子gorountine),并且層層的gorountine需要判斷Done心包。
使用原則
一般context的生存都為一個(gè)request类咧,當(dāng)request結(jié)束的時(shí)候需要把context銷毀。
每次創(chuàng)建一個(gè)gorountine蟹腾,要么將當(dāng)前的context傳遞給這個(gè)gorountine或者創(chuàng)建一個(gè)新的context傳遞給gorountine痕惋。
parent context創(chuàng)建子context的時(shí)候,可以獲得一個(gè)cancel fun岭佳,來控制子gorountine的流程血巍。
當(dāng)子context傳遞到goroutine應(yīng)該監(jiān)控Done對(duì)應(yīng)的channel,如果上層context關(guān)閉珊随,就需要做相應(yīng)的處理。
使用注意
- cancel類型的context在使用的最后一定要調(diào)用cancel釋放資源柿隙,不然有可能Done沒有被使用叶洞,導(dǎo)致資源無法被釋放≠餮拢或者parent對(duì)應(yīng)的context Done close了衩辟。所有在代碼中應(yīng)該盡量及早的cancel對(duì)應(yīng)context
使用模式
-
控制goroutine的生命周期
- 主動(dòng)cancel一個(gè)goroutine,通過withcancel生成對(duì)應(yīng)的child context和cancel波附,在一定條件下由于父親goroutine 進(jìn)行cancel調(diào)用
- Timeout 調(diào)用(不管對(duì)應(yīng)的child goroutine是否結(jié)束都應(yīng)該調(diào)用cancel來釋放資源)通常會(huì)在defer中使用
- Deadline 調(diào)用
不過控制goroutine聲明周期的方法還可以使用一個(gè) read chan的方式來實(shí)現(xiàn)艺晴,但是select并不知道多久會(huì)返回,所以可以配置waitgroup
任務(wù)或者請(qǐng)求超時(shí)掸屡,然后中斷啟的所有子任務(wù)的方法
不同的Goroutine攜帶各自的value變量封寞。