Kaip struktūruoti kontekstai Go kalboje?
sobes.tech AI
Atsakymas iš AI
context (context.Context) Go kalboje naudojamas informacijos perdavimui apie terminus, atšaukimus ir kitus duomenis tarp API ribų. Jis vaizduojamas kaip medis: kiekvienas kontekstas yra kito vaikas, išskyrus šaknį (context.Background() arba context.TODO()).
Pagrindiniai context.Context sąsajos metodai:
Deadline() (deadline time.Time, ok bool): Grąžina konteksto terminą.Done() <-chan struct{}: Grąžina kanalą, kuris užsidaro, kai kontekstas atšaukiamas.Err() error: Grąžina klaidą, kuri lėmė konteksto atšaukimą.Value(key any) any: Grąžina reikšmę, susijusią su raktu kontekste.
Sukuriama naudojant context paketo funkcijas:
context.Background(): Šakninis tuščias kontekstas, naudojamas kaip pagrindas pagrindiniam procesui.context.TODO(): Naudojamas kaip laikina vieta, kai nežinoma, kurį kontekstą naudoti.context.WithCancel(parent Context): Sukuria vaikų kontekstą ir atšaukimo funkciją.context.WithDeadline(parent Context, d time.Time): Sukuria vaikų kontekstą su terminu.context.WithTimeout(parent Context, timeout time.Duration): Sukuria vaikų kontekstą su laiko limitu.context.WithValue(parent Context, key, val any): Sukuria vaikų kontekstą su reikšme.
Pagrindinės Context įgyvendinimai:
emptyCtx: Pagrindinis, neatskiriamas ir be reikšmių. NaudojamiBackgroundirTODO.cancelCtx: Palaiko atšaukimą. Sudarytas iš pagrindinio konteksto ir atšaukimo kanalo.timerCtx: Palaiko terminą / laikmatį. TuricancelCtxir laikmatį.valueCtx: Palaiko reikšmių perdavimą. Turi pagrindinį kontekstą ir raktas-reikšmė porą.
Kai tėvų kontekstas atšaukiamas, automatiškai atšaukiami visi jo vaikai. Tai leidžia plisti atšaukimo signalus arba terminus per kvietimų grandinę.
Pavyzdys naudojant context.WithCancel:
package main
import (
"context"
"fmt"
"time"
)
func main() {
// Sukuriamas pagrindinis kontekstas ir atšaukimo funkcija
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // Garantuoja atšaukimą išėjimo metu
go func() {
select {
case <-ctx.Done(): // Laukia konteksto atšaukimo
fmt.Println("Užduotis atšaukta:", ctx.Err())
return
case <-time.After(5 * time.Second): // Arba baigiasi po 5 sekundžių
fmt.Println("Užduotis įvykdyta")
}
}()
// Atšaukia kontekstą iš kitos vietos
time.Sleep(1 * time.Second)
fmt.Println("Atšaukiama kontekstas...")
cancel()
// Duoda laiko gorutinai apdoroti atšaukimą
time.Sleep(100 * time.Millisecond)
}
Pavyzdys naudojant 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("Apdorojama užklausa User ID:", userID)
} else {
fmt.Println("User ID nerastas kontekste")
}
}
func main() {
ctx := context.WithValue(context.Background(), userIDKey("UserID"), "12345")
processRequest(ctx)
}
Kontekstai yra saugūs kelių gijų ir nekintami, kas yra svarbu konkurenciniam kodui. Jie nėra skirti perduoti neapdorotus funkcijos parametrus, o greičiau metainformacijai, kuri daro įtaką proceso vykdymui.