Ako sú štruktúrované kontexty v jazyku Go?
sobes.tech AI
Odpoveď od AI
context (context.Context) v Go sa používa na prenos informácií o lehotách, zrušeniach a ďalších údajoch medzi hranicami API. Predstavuje strom: každý kontext je dcérskym prvkom iného, okrem koreňového (context.Background() alebo context.TODO()).
Hlavné metódy rozhrania context.Context:
Deadline() (deadline time.Time, ok bool): Vráti časový limit kontextu.Done() <-chan struct{}: Vráti kanál, ktorý sa zatvorí pri zrušení kontextu.Err() error: Vráti chybu, ktorá viedla k zrušeniu kontextu.Value(key any) any: Vráti hodnotu spojenú s kľúčom v kontexte.
Vytvárajú sa pomocou funkcií balíka context:
context.Background(): Koreňový prázdny kontext, používa sa ako základ pre hlavný proces.context.TODO(): Používa sa ako dočasná náhrada, keď nie je známe, ktorý kontext použiť.context.WithCancel(parent Context): Vytvára dcérsky kontext a funkciu na zrušenie.context.WithDeadline(parent Context, d time.Time): Vytvára dcérsky kontext s časovým limitom.context.WithTimeout(parent Context, timeout time.Duration): Vytvára dcérsky kontext s časovým limitom.context.WithValue(parent Context, key, val any): Vytvára dcérsky kontext s hodnotou.
Hlavné implementácie Context:
emptyCtx: Základný, nezrušiteľný a bez hodnôt. Používajú saBackgroundaTODO.cancelCtx: Podporuje zrušenie. Skladá sa zo základného kontextu a kanála na zrušenie.timerCtx: Podporuje časový limit / časovač. ObsahujecancelCtxa časovač.valueCtx: Podporuje prenos hodnôt. Obsahuje základný kontext a kľúč-hodnotu.
Pri zrušení rodičovského kontextu sú automaticky zrušené všetky jeho dcérske. To umožňuje šírenie signálov zrušenia alebo časových limitov cez reťazec volaní.
Príklad použitia context.WithCancel:
package main
import (
"context"
"fmt"
"time"
)
func main() {
// Vytvorenie koreňového kontextu a funkcie na zrušenie
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // Zabezpečí zrušenie pri ukončení main
go func() {
select {
case <-ctx.Done(): // Čaká na zrušenie kontextu
fmt.Println("Úloha zrušená:", ctx.Err())
return
case <-time.After(5 * time.Second): // Ale skončí za 5 sekúnd
fmt.Println("Úloha dokončená")
}
}()
// Zrušenie kontextu z iného miesta
time.Sleep(1 * time.Second)
fmt.Println("Zrušenie kontextu...")
cancel()
// Dávame čas goroutine spracovať zrušenie
time.Sleep(100 * time.Millisecond)
}
Príklad použitia context.WithValue:
package main
import (
"context"
"fmt"
)
type userIDKey string
func processRequest(ctx context.Context) {
if userID, ok := ctx.Value(userIDKey("UserID")).(string); ok {
fmt.Println("Spracovanie požiadavky pre User ID:", userID)
} else {
fmt.Println("User ID nenájdené v kontexte")
}
}
func main() {
ctx := context.WithValue(context.Background(), userIDKey("UserID"), "12345")
processRequest(ctx)
}
Kontexty sú bezpečné pre vlákna a nemenné, čo je dôležité pre konkurenčný kód. Nie sú určené na prenos nestrukturovaných parametrov funkcie, ale skôr na meta-informácie, ktoré ovplyvňujú vykonávanie procesu.