亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入了解Go語言中context的用法

 更新時(shí)間:2023年07月02日 09:07:03   作者:AlwaysBeta  
這篇文章主要為大家詳細(xì)介紹了Go語言中context用法的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

很多 Go 項(xiàng)目的源碼,在讀的過程中會(huì)發(fā)現(xiàn)一個(gè)很常見的參數(shù) ctx,而且基本都是作為函數(shù)的第一個(gè)參數(shù)。

為什么要這么寫呢?這個(gè)參數(shù)到底有什么用呢?帶著這樣的疑問,我研究了這個(gè)參數(shù)背后的故事。

開局一張圖:

核心是 Context 接口:

//?A?Context?carries?a?deadline,?cancelation?signal,?and?request-scoped?values
//?across?API?boundaries.?Its?methods?are?safe?for?simultaneous?use?by?multiple
//?goroutines.
type?Context?interface?{
????//?Done?returns?a?channel?that?is?closed?when?this?Context?is?canceled
????//?or?times?out.
????Done()?<-chan?struct{}
????//?Err?indicates?why?this?context?was?canceled,?after?the?Done?channel
????//?is?closed.
????Err()?error
????//?Deadline?returns?the?time?when?this?Context?will?be?canceled,?if?any.
????Deadline()?(deadline?time.Time,?ok?bool)
????//?Value?returns?the?value?associated?with?key?or?nil?if?none.
????Value(key?interface{})?interface{}
}

包含四個(gè)方法:

  • Done():返回一個(gè) channel,當(dāng) times out 或者調(diào)用 cancel 方法時(shí)。
  • Err():返回一個(gè)錯(cuò)誤,表示取消 ctx 的原因。
  • Deadline():返回截止時(shí)間和一個(gè) bool 值。
  • Value():返回 key 對(duì)應(yīng)的值。

有四個(gè)結(jié)構(gòu)體實(shí)現(xiàn)了這個(gè)接口,分別是:emptyCtxcancelCtxtimerCtx 和 valueCtx。

其中 emptyCtx 是空類型,暴露了兩個(gè)方法:

func?Background()?Context
func?TODO()?Context

一般情況下,會(huì)使用 Background() 作為根 ctx,然后在其基礎(chǔ)上再派生出子 ctx。要是不確定使用哪個(gè) ctx,就使用 TODO()。

另外三個(gè)也分別暴露了對(duì)應(yīng)的方法:

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

遵循規(guī)則

在使用 Context 時(shí),要遵循以下四點(diǎn)規(guī)則:

  • 不要將 Context 放入結(jié)構(gòu)體,而是應(yīng)該作為第一個(gè)參數(shù)傳入,命名為 ctx。
  • 即使函數(shù)允許,也不要傳入 nil 的 Context。如果不知道用哪種 Context,可以使用 context.TODO()。
  • 使用 Context 的 Value 相關(guān)方法只應(yīng)該用于在程序和接口中傳遞和請(qǐng)求相關(guān)的元數(shù)據(jù),不要用它來傳遞一些可選的參數(shù)。
  • 相同的 Context 可以傳遞給不同的 goroutine;Context 是并發(fā)安全的。

WithCancel

func?WithCancel(parent?Context)?(ctx?Context,?cancel?CancelFunc)

WithCancel 返回帶有新 Done 通道的父級(jí)副本。當(dāng)調(diào)用返回的 cancel 函數(shù)或關(guān)閉父上下文的 Done 通道時(shí),返回的 ctx 的 Done 通道將關(guān)閉。

取消此上下文會(huì)釋放與其關(guān)聯(lián)的資源,因此在此上下文中運(yùn)行的操作完成后,代碼應(yīng)立即調(diào)用 cancel

舉個(gè)例子:

這段代碼演示了如何使用可取消上下文來防止 goroutine 泄漏。在函數(shù)結(jié)束時(shí),由 gen 啟動(dòng)的 goroutine 將返回而不會(huì)泄漏。

package?main
import?(
????"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
????????}
????}
}

輸出:

1
2
3
4
5

WithDeadline

func?WithDeadline(parent?Context,?d?time.Time)?(Context,?CancelFunc)

WithDeadline 返回父上下文的副本,并將截止日期調(diào)整為不晚于 d。如果父級(jí)的截止日期已經(jīng)早于 d,則 WithDeadline(parent, d) 在語義上等同于 parent。

當(dāng)截止時(shí)間到期、調(diào)用返回的取消函數(shù)時(shí)或當(dāng)父上下文的 Done 通道關(guān)閉時(shí),返回的上下文的 Done 通道將關(guān)閉。

取消此上下文會(huì)釋放與其關(guān)聯(lián)的資源,因此在此上下文中運(yùn)行的操作完成后,代碼應(yīng)立即調(diào)用取消。

舉個(gè)例子:

這段代碼傳遞具有截止時(shí)間的上下文,來告訴阻塞函數(shù),它應(yīng)該在到達(dá)截止時(shí)間時(shí)立刻退出。

package?main
import?(
????"context"
????"fmt"
????"time"
)
const?shortDuration?=?1?*?time.Millisecond
func?main()?{
????d?:=?time.Now().Add(shortDuration)
????ctx,?cancel?:=?context.WithDeadline(context.Background(),?d)
????//?Even?though?ctx?will?be?expired,?it?is?good?practice?to?call?its
????//?cancellation?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

WithTimeout

func?WithTimeout(parent?Context,?timeout?time.Duration)?(Context,?CancelFunc)

WithTimeout 返回 WithDeadline(parent, time.Now().Add(timeout))。

取消此上下文會(huì)釋放與其關(guān)聯(lián)的資源,因此在此上下文中運(yùn)行的操作完成后,代碼應(yīng)立即調(diào)用取消。

舉個(gè)例子:

這段代碼傳遞帶有超時(shí)的上下文,以告訴阻塞函數(shù)應(yīng)在超時(shí)后退出。

package?main
import?(
????"context"
????"fmt"
????"time"
)
const?shortDuration?=?1?*?time.Millisecond
func?main()?{
????//?Pass?a?context?with?a?timeout?to?tell?a?blocking?function?that?it
????//?should?abandon?its?work?after?the?timeout?elapses.
????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())?//?prints?"context?deadline?exceeded"
????}
}

輸出:

context deadline exceeded

WithValue

func?WithValue(parent?Context,?key,?val?any)?Context

WithValue 返回父級(jí)的副本,其中與 key 關(guān)聯(lián)的值為 val。

其中鍵必須是可比較的,并且不應(yīng)是字符串類型或任何其他內(nèi)置類型,以避免使用上下文的包之間發(fā)生沖突。 WithValue 的用戶應(yīng)該定義自己的鍵類型。

為了避免分配給 interface{},上下文鍵通常具有具體的 struct{} 類型?;蛘撸瑢?dǎo)出的上下文鍵變量的靜態(tài)類型應(yīng)該是指針或接口。

舉個(gè)例子:

這段代碼演示了如何將值傳遞到上下文以及如何檢索它(如果存在)。

package?main
import?(
????"context"
????"fmt"
)
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: Go
key not found: color

本文的大部分內(nèi)容,包括代碼示例都是翻譯自官方文檔,代碼都是經(jīng)過驗(yàn)證可以執(zhí)行的。如果有不是特別清晰的地方,可以直接去讀官方文檔。

以上就是深入了解Go語言中context的用法的詳細(xì)內(nèi)容,更多關(guān)于Go context的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang反射模塊reflect使用方式示例詳解

    Golang反射模塊reflect使用方式示例詳解

    Golang的反射功能,在很多場(chǎng)景都會(huì)用到,最基礎(chǔ)的莫過于rpc、orm跟json的編解碼,更復(fù)雜的可能會(huì)到做另外一門語言的虛擬機(jī),這篇文章主要介紹了Golang反射模塊reflect使用方式探索,需要的朋友可以參考下
    2023-01-01
  • Go語言的IO庫那么多糾結(jié)該如何選擇

    Go語言的IO庫那么多糾結(jié)該如何選擇

    在Go語言中涉及 I/O 操作的內(nèi)置庫有很多種,比如: io 庫, os 庫, ioutil 庫, bufio 庫, bytes 庫, strings 庫等等。擁有這么多內(nèi)置庫是好事,但是具體到涉及 I/O 的場(chǎng)景我們應(yīng)該選擇哪個(gè)庫呢,帶著這個(gè)問題一起通過本文學(xué)習(xí)下吧
    2021-06-06
  • go語言實(shí)現(xiàn)猜數(shù)字小游戲的方法

    go語言實(shí)現(xiàn)猜數(shù)字小游戲的方法

    這篇文章主要介紹了go語言實(shí)現(xiàn)猜數(shù)字小游戲的方法,實(shí)例分析了Go語言流程判斷與處理的技巧,需要的朋友可以參考下
    2015-03-03
  • go?mod文件內(nèi)容版本號(hào)簡(jiǎn)單用法詳解

    go?mod文件內(nèi)容版本號(hào)簡(jiǎn)單用法詳解

    這篇文章主要為大家介紹了go?mod文件內(nèi)容版本號(hào)簡(jiǎn)單用法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Go 切片導(dǎo)致內(nèi)存泄露的幾種原因

    Go 切片導(dǎo)致內(nèi)存泄露的幾種原因

    某些情況下,對(duì)一個(gè)已存在的切片或數(shù)組進(jìn)行切分操作可能會(huì)導(dǎo)致內(nèi)存泄漏,本文主要介紹了Go 切片導(dǎo)致內(nèi)存泄露的幾種原因,感興趣的可以了解一下
    2023-05-05
  • 如何使用Go語言實(shí)現(xiàn)基于泛型的Jaccard相似度算法

    如何使用Go語言實(shí)現(xiàn)基于泛型的Jaccard相似度算法

    這篇文章主要介紹了如何使用Go語言實(shí)現(xiàn)基于泛型的Jaccard相似度算法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-08-08
  • 淺析Go語言中包的介紹與初始化

    淺析Go語言中包的介紹與初始化

    這篇文章主要為大家詳細(xì)介紹了Go語言中包的介紹與初始化,從而搞清Go程序的執(zhí)行次序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解下
    2023-10-10
  • Golang channel死鎖的幾種情況小結(jié)

    Golang channel死鎖的幾種情況小結(jié)

    本文主要介紹了Golang channel死鎖的幾種情況小結(jié),詳細(xì)的介紹了六種情況,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • GoFrame?gredis配置文件及配置方法對(duì)比

    GoFrame?gredis配置文件及配置方法對(duì)比

    這篇文章主要為大家介紹了GoFrame?gredis配置管理中,配置文件及配置方法對(duì)比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 讀取Go項(xiàng)目中的配置文件的方法

    讀取Go項(xiàng)目中的配置文件的方法

    本文主要介紹了讀取Go項(xiàng)目中的配置文件的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06

最新評(píng)論