一文讓你理解go語言的Context
Context上下文
Context的出現(xiàn)是為了解決在大型應(yīng)用程序中的并發(fā)環(huán)境下,協(xié)調(diào)和管理多個goroutine之間的通信、超時和取消操作的問題。它提供了一種標準化的機制,以便在程序的不同部分之間傳遞請求相關(guān)的值,并且可以在整個調(diào)用鏈中傳播和取消這些值。
Context的主要目的是:
- 傳遞請求范圍的值:通過Context,可以在不同的函數(shù)調(diào)用中傳遞請求相關(guān)的值,例如請求ID、用戶認證信息、日志記錄器等。這樣可以避免在函數(shù)之間顯式傳遞這些值,使代碼更加清晰簡潔。
- 控制并發(fā)操作:通過Context的取消信號,可以通知相關(guān)的goroutine停止運行并返回,從而實現(xiàn)對并發(fā)操作的控制。這對于處理長時間運行的操作或避免資源泄漏非常有用。
- 設(shè)置截止時間:Context允許為操作設(shè)置截止時間,超過該時間則自動取消相關(guān)的操作。這對于避免長時間等待或超時的情況非常有用,可以提高系統(tǒng)的可靠性和性能。
- 傳播和繼承:通過Context,可以在整個調(diào)用鏈中傳播和繼承請求范圍的值和取消信號,而無需顯式地傳遞它們。這樣可以減少代碼中的重復(fù)操作,并確保所有相關(guān)的goroutine都能收到相同的上下文信息。
總而言之,Context的出現(xiàn)是為了提供一種統(tǒng)一的機制,用于管理并發(fā)操作、傳遞請求相關(guān)的值和控制操作的超時和取消。它簡化了并發(fā)編程模型,提高了代碼的可讀性、可維護性和可測試性。
1. Context接口定義
?type Context interface { ? ?Deadline() (deadline time.Time, ok bool) ? ?Done <-chan struct{} ? ?Err() error ? ?Value(key interface{}) interface{} ?}
Deadline() (deadline time.Time, ok bool)
:方法功能: Deadline方法返回代表此上下文中的工作應(yīng)該被取消的時間。當沒有設(shè)置截止時間時,Deadline方法返回ok==false。連續(xù)調(diào)用Deadline方法將返回相同的結(jié)果:
deadline
:表示Context的截止時間,如果沒有設(shè)置截止時間或截止時間已過,則返回零值Deadline方法返回ok==false。ok
:布爾值,指示截止時間是否存在。如果存在截止時間,則為true
;否則為false
。
Done() <-chan struct{}
:方法功能:返回一個只讀的通道(
<-chan struct{}
),該通道在Context被取消或過期時關(guān)閉。返回值:返回一個只讀的通道,可以通過該通道接收到Context的取消或過期信號。
Err() error
:方法功能:返回Context被取消的原因(錯誤信息)。
返回值:
- 如果Context已被取消,返回一個非空的錯誤對象,描述取消的原因。
- 如果Context尚未被取消,或者取消原因未知,則返回
nil
。
Value(key interface{}) interface{}
:方法功能:根據(jù)給定的鍵(key),返回與Context相關(guān)聯(lián)的值。
參數(shù):
key
表示要檢索的值的鍵。返回值:
- 如果Context關(guān)聯(lián)的值存在,則返回與給定鍵關(guān)聯(lián)的值(類型為
interface{}
)。 - 如果不存在與給定鍵關(guān)聯(lián)的值,則返回
nil
。
- 如果Context關(guān)聯(lián)的值存在,則返回與給定鍵關(guān)聯(lián)的值(類型為
2. 錯誤設(shè)置
?// Canceled is the error returned by Context.Err when the context is canceled. ?var Canceled = errors.New("context canceled") ?? ?// DeadlineExceeded is the error returned by Context.Err when the context's ?// deadline passes. ?var DeadlineExceeded error = deadlineExceededError{} ?? ?type deadlineExceededError struct{} ?? ?func (deadlineExceededError) Error() string ? { return "context deadline exceeded" } ?func (deadlineExceededError) Timeout() bool ? { return true } ?func (deadlineExceededError) Temporary() bool { return true } ??
在上述代碼中,定義了兩個預(yù)定義的錯誤變量:Canceled和DeadlineExceeded,用于表示上下文取消和超時。
Canceled
是在上下文被取消時由Context.Err
返回的錯誤。它是一個errors.New
創(chuàng)建的錯誤,表示上下文已被取消。
DeadlineExceeded
是在上下文的截止時間過去時由Context.Err
返回的錯誤。它是一個自定義的錯誤類型deadlineExceededError
的實例。該類型實現(xiàn)了error
接口的方法。
Error()
方法返回表示上下文截止時間已過的錯誤字符串,即"context deadline exceeded"。Timeout()
方法返回true
,指示該錯誤是由于超時引起的。Temporary()
方法返回true
,指示該錯誤是臨時性的。
3. emptyCtx
?type emptyCtx int ?? ?func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { ? return ?} ?? ?func (*emptyCtx) Done() <-chan struct{} { ? return nil ?} ?? ?func (*emptyCtx) Err() error { ? return nil ?} ?? ?func (*emptyCtx) Value(key any) any { ? return nil ?} ?? ?func (e *emptyCtx) String() string { ? switch e { ? case background: ? return "context.Background" ? case todo: ? return "context.TODO" ? } ? return "unknown empty Context" ?}
emptyCtx
是一個空的上下文類型。它具有以下特點:
- 永遠不會被取消:
emptyCtx
是一個不可取消的上下文,即沒有任何操作會導(dǎo)致它被取消。 - 沒有值:
emptyCtx
不存儲任何與其關(guān)聯(lián)的值。 - 沒有截止時間:
emptyCtx
沒有設(shè)置任何截止時間,即沒有截止時間的限制。
emptyCtx
的類型不是struct{}
,因為這樣的變量必須具有不同的地址。實際上,emptyCtx
是一個內(nèi)部類型,用于表示一個特殊的空上下文。
該空上下文在一些特殊情況下使用,例如作為根上下文或默認上下文,在沒有顯式提供上下文的情況下,可以使用它來代替。由于其不可取消、沒有值和截止時間的特性,它在某些場景下提供了一個空的占位符上下文實例。
4. 兩個emptyCtx
?? ?var ( ? background = new(emptyCtx) ? todo ? ? ? = new(emptyCtx) ?) ?? ?func Background() Context { ? return background ?} ?? ?func TODO() Context { ? return todo ?} ??
4.1. Background
Background
函數(shù)返回一個非空的空上下文。它具有以下特點:
- 永遠不會被取消:
Background
上下文是一個不可取消的上下文,即沒有任何操作會導(dǎo)致它被取消。 - 沒有值:
Background
上下文不存儲任何與其關(guān)聯(lián)的值。 - 沒有截止時間:
Background
上下文沒有設(shè)置任何截止時間,即沒有截止時間的限制。
Background
上下文是一個常用的上下文實例,通常用于主函數(shù)、初始化過程、測試以及作為傳入請求的頂級上下文。它提供了一個空的占位符上下文,適用于不需要具體上下文的場景。由于其不可取消、沒有值和截止時間的特性,Background
上下文在啟動程序、進行初始化操作以及處理入站請求時經(jīng)常被使用。
4.2. TODO
TODO
函數(shù)返回一個非空的空上下文。在代碼中,當不清楚使用哪個上下文或者上下文尚不可用(因為周圍的函數(shù)尚未被擴展為接受上下文參數(shù))時,應(yīng)使用context.TODO
。
TODO
上下文是一個臨時的占位符上下文,用于表示上下文尚未確定或不可用的情況。它可以作為編碼過程中的一種暫時解決方案,在代碼進一步完善之前使用。當需要傳遞上下文但還沒有明確選擇使用哪個上下文時,可以使用TODO
來占位,以后根據(jù)具體情況進行替換。
5. CancleFun
?// A CancelFunc tells an operation to abandon its work. ?// A CancelFunc does not wait for the work to stop. ?// A CancelFunc may be called by multiple goroutines simultaneously. ?// After the first call, subsequent calls to a CancelFunc do nothing. ?type CancelFunc func()
CancelFunc
是一個函數(shù)類型,用于通知某個操作放棄其工作。CancelFunc
不會等待工作停止,它僅僅是發(fā)送一個取消信號。CancelFunc
可以被多個 goroutine 同時調(diào)用。第一次調(diào)用之后,對 CancelFunc
的后續(xù)調(diào)用不會產(chǎn)生任何效果。
當需要取消某個操作時,可以調(diào)用 CancelFunc
函數(shù),以通知相關(guān)的操作停止工作。這個函數(shù)類型可以與 context.WithCancel
、context.WithDeadline
、context.WithTimeout
等函數(shù)一起使用,這些函數(shù)在創(chuàng)建派生的上下文時會返回一個 CancelFunc
。
需要注意的是,調(diào)用 CancelFunc
只是向操作發(fā)送一個取消信號,具體的操作是否真正停止取決于操作本身的實現(xiàn)。CancelFunc
的調(diào)用不會阻塞,它會立即返回。
在使用 CancelFunc
時,應(yīng)注意并發(fā)調(diào)用的情況,因為它可以被多個 goroutine 同時調(diào)用。確保在并發(fā)情況下正確處理取消操作,以避免潛在的競態(tài)條件和問題。
6. cancleCtx
?type cancelCtx struct { ? Context ?? ? mu ? ? ? sync.Mutex ? ? ? ? ? ?// protects following fields ? done ? ? atomic.Value ? ? ? ? ?// of chan struct{}, created lazily, closed by first cancel call ? children map[canceler]struct{} // set to nil by the first cancel call ? err ? ? ?error ? ? ? ? ? ? ? ? // set to non-nil by the first cancel call ? cause ? ?error ? ? ? ? ? ? ? ? // set to non-nil by the first cancel call ?}
cancelCtx
是 context
包中定義的一個結(jié)構(gòu)體類型,實現(xiàn)了 Context
接口。它是基于取消機制的上下文類型,用于表示可以被取消的上下文。
下面是 cancelCtx
結(jié)構(gòu)體的詳細介紹:
Context
:嵌入字段,表示cancelCtx
結(jié)構(gòu)體實現(xiàn)了Context
接口,可以被用作上下文對象。mu
:sync.Mutex
類型的互斥鎖,用于保護以下字段的并發(fā)訪問。done
:atomic.Value
類型的原子值,用于存儲一個chan struct{}
,該通道在首次取消調(diào)用時被關(guān)閉。該字段是惰性創(chuàng)建的,即在首次取消調(diào)用之前為nil
。它用于通知相關(guān)的 goroutine 上下文已被取消。children
:map[canceler]struct{}
類型的字段,用于存儲與該上下文關(guān)聯(lián)的子上下文(通過WithCancel
、WithDeadline
或WithTimeout
創(chuàng)建)。子上下文被存儲在該映射中作為鍵,對應(yīng)的值為空結(jié)構(gòu)。在首次取消調(diào)用后,該字段會被設(shè)置為nil
。err
:error
類型的字段,用于存儲上下文的取消錯誤。在首次取消調(diào)用后,該字段會被設(shè)置為非nil
的錯誤值。cause
:error
類型的字段,用于存儲上下文的取消原因。在首次取消調(diào)用后,該字段會被設(shè)置為非nil
的錯誤值。
cancelCtx
結(jié)構(gòu)體用于實現(xiàn)上下文的取消機制。當調(diào)用 cancel
方法時,會通過關(guān)閉 done
通道來通知相關(guān)的 goroutine 上下文已被取消。同時,會設(shè)置 err
字段為取消錯誤,并記錄取消原因(如果提供了)。子上下文也會被取消,即它們的 cancel
方法會被調(diào)用,并將自身從 children
映射中刪除。
這種基于取消機制的上下文類型可以用于在多個 goroutine 之間傳遞取消信號,使得相關(guān)的操作可以在需要時及時終止。
7. WithCancel
?func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { ? c := withCancel(parent) ? return c, func() { c.cancel(true, Canceled, nil) } ?}
WithCancel
函數(shù)的主要特點和步驟:
- 返回一個基于父上下文的副本,并創(chuàng)建一個新的
Done
通道。 - 當調(diào)用返回的
cancel
函數(shù)或者父上下文的Done
通道關(guān)閉時,返回的上下文的Done
通道也會被關(guān)閉。 - 調(diào)用
cancel
函數(shù)會釋放與上下文相關(guān)的資源,因此在操作完成后應(yīng)盡快調(diào)用。 - 使用
WithCancel
創(chuàng)建的上下文可以手動取消操作,并確保及時釋放資源。
?func Cancel() { ? // 創(chuàng)建一個帶有取消功能的上下文 ? ctx, cancel := context.WithCancel(context.Background()) ?? ? // 啟動一個 goroutine 來執(zhí)行定時任務(wù) ? go func() { ? for { ? select { ? case <-ctx.Done(): ? fmt.Println("定時任務(wù)被取消") ? return ? default: ? // 模擬定時任務(wù)的工作 ? fmt.Println("執(zhí)行定時任務(wù)...") ? time.Sleep(1 * time.Second) ? } ? } ? }() ?? ? // 模擬等待一段時間后取消定時任務(wù) ? time.Sleep(5 * time.Second) ? cancel() ?? ? // 等待一段時間以觀察任務(wù)的狀態(tài) ? time.Sleep(2 * time.Second) ?} ??
wangyufan@wangcomputerair MINGW64 /d/goworkplace/src/github.com/context (master)
$ go run .
執(zhí)行定時任務(wù)...
執(zhí)行定時任務(wù)...
執(zhí)行定時任務(wù)...
執(zhí)行定時任務(wù)...
執(zhí)行定時任務(wù)...
定時任務(wù)被取消
在這個例子中,我們創(chuàng)建了一個帶有取消功能的上下文(ctx
)和對應(yīng)的取消函數(shù)(cancel
)。然后,我們啟動了一個 goroutine 來執(zhí)行定時任務(wù),每隔一秒鐘輸出一次"執(zhí)行定時任務(wù)..."。在主函數(shù)中,我們等待了5秒鐘后調(diào)用cancel
函數(shù),發(fā)送取消信號。最后,我們等待2秒鐘以觀察任務(wù)的狀態(tài)。
通過運行這個示例,你可以觀察到在取消信號發(fā)送后,定時任務(wù)會立即停止執(zhí)行,輸出"定時任務(wù)被取消",而不會繼續(xù)執(zhí)行剩余的定時任務(wù)。這展示了使用context.WithCancel()
取消任務(wù)的現(xiàn)象明顯的例子
8. WithDeadline
?func WithDeadline(parent Context, d time.Time) (Context, CancelFunc){}
WithDeadline
函數(shù)返回一個基于父上下文 parent
的副本,并設(shè)置一個截止時間 d
。返回的上下文對象具有一個新的 Done
通道,當截止時間到達或者父上下文的 Done
通道關(guān)閉時(以先發(fā)生者為準),該 Done
通道將被關(guān)閉。
取消該上下文會釋放與其相關(guān)聯(lián)的資源,因此,在使用該上下文執(zhí)行的操作完成后,代碼應(yīng)盡快調(diào)用 cancel
函數(shù)。
WithDeadline
函數(shù)的作用是創(chuàng)建一個帶有截止時間的上下文??梢允褂迷撋舷挛膩砜刂撇僮鞯膱?zhí)行時間,一旦截止時間到達,相關(guān)操作可以被取消或中止。
需要注意的是,截止時間是一個絕對時間,可以使用 time.Now()
結(jié)合 time.Duration
來指定一個相對于當前時間的截止時間。
WithDeadline
函數(shù)的主要特點和步驟如下:
- 返回一個基于父上下文的副本,并設(shè)置截止時間為
d
。 - 創(chuàng)建一個新的
Done
通道,當截止時間到達或者父上下文的Done
通道關(guān)閉時,該Done
通道將被關(guān)閉。 - 調(diào)用
cancel
函數(shù)會釋放與上下文相關(guān)的資源,因此在操作完成后應(yīng)盡快調(diào)用。 - 使用
WithDeadline
創(chuàng)建的上下文可以控制操作的執(zhí)行時間,并在截止時間到達時取消或中止相關(guān)操作。
?func Dead() { ? ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second)) ?? ? // 啟動一個 goroutine 來執(zhí)行任務(wù) ? go func() { ? for { ? select { ? case <-ctx.Done(): ? fmt.Println("任務(wù)被取消:", ctx.Err()) ? return ? default: ? // 模擬任務(wù)的工作 ? fmt.Println("執(zhí)行任務(wù)...") ? time.Sleep(1 * time.Second) ? } ? } ? }() ?? ? // 等待一段時間以觀察任務(wù)的狀態(tài) ? time.Sleep(8 * time.Second) ?? ? // 取消任務(wù) ? cancel() ?? ? // 等待一段時間以觀察任務(wù)的狀態(tài) ? time.Sleep(2 * time.Second) ?}
wangyufan@wangcomputerair MINGW64 /d/goworkplace/src/github.com/context (master)
$ go run .
執(zhí)行任務(wù)...
執(zhí)行任務(wù)...
執(zhí)行任務(wù)...
執(zhí)行任務(wù)...
執(zhí)行任務(wù)...
任務(wù)被取消: context deadline exceeded
在這個示例中,我們使用context.WithDeadline()
創(chuàng)建了一個具有截止時間的上下文(ctx
)和對應(yīng)的取消函數(shù)(cancel
)。通過調(diào)用time.Now().Add(5*time.Second)
,我們設(shè)置了截止時間為當前時間5秒后。然后,我們啟動了一個 goroutine 來執(zhí)行任務(wù),每隔一秒鐘輸出一次"執(zhí)行任務(wù)..."。在主函數(shù)中,我們等待了8秒鐘,超過了截止時間,然后調(diào)用cancel
函數(shù)取消任務(wù)。最后,我們等待2秒鐘以觀察任務(wù)的狀態(tài)。
通過運行這個示例,你可以觀察到在截止時間到達后,任務(wù)會立即停止執(zhí)行,并輸出"任務(wù)被取消"。這展示了使用context.WithDeadline()
設(shè)置截止時間并取消任務(wù)的示例。
9. WithTimeOut
?func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { ? return WithDeadline(parent, time.Now().Add(timeout)) ?}
WithTimeout
函數(shù)是 context
包中的一個輔助函數(shù),它基于父上下文 parent
和超時時間 timeout
創(chuàng)建一個新的上下文,并返回該上下文以及對應(yīng)的取消函數(shù)。
函數(shù)的內(nèi)部實現(xiàn)是調(diào)用了 WithDeadline
函數(shù),將當前時間加上超時時間得到截止時間,然后將截止時間作為參數(shù)調(diào)用 WithDeadline
,返回相應(yīng)的上下文和取消函數(shù)。
簡而言之,WithTimeout
函數(shù)是使用相對于當前時間的超時時間來創(chuàng)建一個帶有截止時間的上下文。超時時間可以是一個持續(xù)時間(time.Duration
)對象,表示從當前時間開始的一段時間。
使用 WithTimeout
函數(shù)可以方便地創(chuàng)建一個具有超時控制的上下文,以確保在超時時間到達后相關(guān)操作可以被取消或中止。
需要注意的是,超時時間應(yīng)該是一個非負值。如果超時時間為零或負值,表示立即超時,即操作將立即取消。
?// TimeOut the function that will be testing the context.WithTimeout ?func TimeOut() { ? // 設(shè)置一個超時時間為5秒的上下文 ? ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ?? ? // 啟動一個 goroutine 來執(zhí)行任務(wù) ? go func() { ? for { ? select { ? case <-ctx.Done(): ? fmt.Println("任務(wù)被取消:", ctx.Err()) ? return ? default: ? // 模擬任務(wù)的工作 ? fmt.Println("執(zhí)行任務(wù)...") ? time.Sleep(1 * time.Second) ? } ? } ? }() ?? ? // 等待一段時間以觀察任務(wù)的狀態(tài) ? time.Sleep(8 * time.Second) ?? ? // 取消任務(wù) ? cancel() ?? ? // 等待一段時間以觀察任務(wù)的狀態(tài) ? time.Sleep(2 * time.Second) ?} ??
wangyufan@wangcomputerair MINGW64 /d/goworkplace/src/github.com/context (master)
$ go run .
執(zhí)行任務(wù)...
執(zhí)行任務(wù)...
執(zhí)行任務(wù)...
執(zhí)行任務(wù)...
執(zhí)行任務(wù)...
任務(wù)被取消: context deadline exceeded
在這個示例中,我們使用context.WithTimeout()
創(chuàng)建了一個具有超時時間的上下文(ctx
)和對應(yīng)的取消函數(shù)(cancel
)。通過設(shè)置超時時間為5秒(5*time.Second
),我們限定了任務(wù)的執(zhí)行時間。然后,我們啟動了一個 goroutine 來執(zhí)行任務(wù),每隔一秒鐘輸出一次"執(zhí)行任務(wù)..."。在主函數(shù)中,我們等待了8秒鐘,超過了超時時間,然后調(diào)用cancel
函數(shù)取消任務(wù)。最后,我們等待2秒鐘以觀察任務(wù)的狀態(tài)。
通過運行這個示例,你可以觀察到在超時時間到達后,任務(wù)會立即停止執(zhí)行,并輸出"任務(wù)被取消"。這展示了使用context.WithTimeout()
設(shè)置超時時間并取消任務(wù)的示例。
10. WithValue
?func WithValue(parent Context, key, val any) Context { ? if parent == nil { ? panic("cannot create context from nil parent") ? } ? if key == nil { ? panic("nil key") ? } ? if !reflectlite.TypeOf(key).Comparable() { ? panic("key is not comparable") ? } ? return &valueCtx{parent, key, val} ?}
WithValue
函數(shù)是 context
包中的一個輔助函數(shù),用于基于父上下文 parent
創(chuàng)建一個新的上下文,并將鍵值對 (key, val)
存儲在新上下文中。函數(shù)返回新的上下文對象。
函數(shù)首先進行了一些參數(shù)校驗,確保 parent
不為空,key
不為 nil
,且 key
是可比較的(comparable)。在 Go 語言中,可比較的類型是指可以使用 ==
運算符進行比較的類型。
然后,函數(shù)創(chuàng)建了一個 valueCtx
結(jié)構(gòu)體,并將父上下文、key
和 val
存儲在該結(jié)構(gòu)體中。valueCtx
是 context
包中定義的一個內(nèi)部類型,用于存儲上下文的鍵值對信息。
最后,函數(shù)返回新創(chuàng)建的 valueCtx
對象,它實現(xiàn)了 Context
接口。
通過使用 WithValue
函數(shù),可以在上下文中存儲和傳遞與請求相關(guān)的數(shù)據(jù),這些數(shù)據(jù)可以被跨 API 邊界和進程邊界傳遞。需要注意的是,WithValue
函數(shù)適用于傳遞請求范圍的數(shù)據(jù),而不應(yīng)該被用于傳遞可選的函數(shù)參數(shù)。
?func Test() { ? // 創(chuàng)建一個父級上下文 ? parent := context.Background() ?? ? // 使用 WithValue 創(chuàng)建一個帶有用戶身份信息的子級上下文 ? user := User{ID: 123, Name: "Alice"} ? ctx := context.WithValue(parent, "user", user) ?? ? // 在不同的函數(shù)中獲取用戶身份信息 ? processRequest(ctx) ?} ?? ?// processRequest a function that get information from ctx ?func processRequest(ctx context.Context) { ? // 從上下文中獲取用戶身份信息 ? user, ok := ctx.Value("user").(User) ? if !ok { ? fmt.Println("無法獲取用戶身份信息") ? return ? } ?? ? // 使用用戶身份信息執(zhí)行請求處理 ? fmt.Printf("處理請求,用戶ID: %d, 用戶名: %s\n", user.ID, user.Name) ?? ? // 調(diào)用其他函數(shù)傳遞上下文 ? otherFunction(ctx) ?} ?? ?// otherFunction another function that get information form ctx ?func otherFunction(ctx context.Context) { ? // 從上下文中獲取用戶身份信息 ? user, ok := ctx.Value("user").(User) ? if !ok { ? fmt.Println("無法獲取用戶身份信息") ? return ? } ?? ? // 使用用戶身份信息執(zhí)行其他操作 ? fmt.Printf("執(zhí)行其他操作,用戶ID: %d, 用戶名: %s\n", user.ID, user.Name) ?} ??
wangyufan@wangcomputerair MINGW64 /d/goworkplace/src/github.com/context (master)
$ go run .
處理請求,用戶ID: 123, 用戶名: Alice
執(zhí)行其他操作,用戶ID: 123, 用戶名: Alice
在這個例子中,我們首先創(chuàng)建了一個父級上下文parent
。然后,我們使用context.WithValue()
將用戶身份信息User{ID: 123, Name: "Alice"}
與上下文關(guān)聯(lián),創(chuàng)建了一個帶有用戶身份信息的子級上下文ctx
。接下來,我們通過調(diào)用processRequest(ctx)
將子級上下文傳遞給處理請求的函數(shù)。
在processRequest
函數(shù)中,我們從上下文中獲取用戶身份信息,并使用該信息執(zhí)行請求處理。然后,我們調(diào)用otherFunction(ctx)
將上下文傳遞給另一個函數(shù)。
在otherFunction
函數(shù)中,我們同樣從上下文中獲取用戶身份信息,并使用該信息執(zhí)行其他操作。
通過運行這個例子,你可以觀察到在不同的函數(shù)中成功獲取到了用戶身份信息,并使用該信息進行相應(yīng)的處理和操作。這展示了如何使用context.WithValue()
將用戶身份信息與上下文關(guān)聯(lián),并在不同的函數(shù)中傳遞和獲取這些信息。
以上就是一文讓你理解go語言的Context的詳細內(nèi)容,更多關(guān)于go Context的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go語言反射reflect.Value實現(xiàn)方法的調(diào)用
本文主要介紹了Go語言反射reflect.Value實現(xiàn)方法的調(diào)用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05GO?CountMinSketch計數(shù)器(布隆過濾器思想的近似計數(shù)器)
這篇文章主要介紹了GO?CountMinSketch計數(shù)器(布隆過濾器思想的近似計數(shù)器),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下2022-09-09Golang?基于flag庫實現(xiàn)一個簡單命令行工具
這篇文章主要介紹了Golang基于flag庫實現(xiàn)一個簡單命令行工具,Golang標準庫中的flag庫提供了解析命令行選項的能力,我們可以基于此來開發(fā)命令行工具,下文詳細介紹。需要的小伙伴可以參考一下2022-08-08