Kako su strukturirani konteksti u jeziku Go?
sobes.tech АИ
Одговор од АИ
Контекст (context.Context) у Go се користи за пренос информација о роковима, отказима и другим подацима између граница API-ја. Он представља дрво: сваки контекст је потомак другог, осим коренског (context.Background() или context.TODO()).
Главне методе интерфејса context.Context:
Deadline() (deadline time.Time, ok bool): Враћа рок контекста.Done() <-chan struct{}: Враћа канал који се затвара приликом отказа контекста.Err() error: Враћа грешку која је довела до отказа контекста.Value(key any) any: Враћа вредност повезану са кључем у контексту.
Креирају се помоћу функција пакета context:
context.Background(): Коренски празан контекст, користи се као основа за главни процес.context.TODO(): Користи се као привремена замена када није познато који контекст користити.context.WithCancel(parent Context): Креира дечији контекст и функцију за отказивање.context.WithDeadline(parent Context, d time.Time): Креира дечији контекст са роком.context.WithTimeout(parent Context, timeout time.Duration): Креира дечији контекст са временским ограничењем.context.WithValue(parent Context, key, val any): Креира дечији контекст са вредношћу.
Главне имплементације Context:
emptyCtx: Основни, неотказиви и без вредности. Користе сеBackgroundиTODO.cancelCtx: Подржава отказивање. Састоји се од основног контекста и канала за отказивање.timerCtx: Подржава рок/таймер. СадржиcancelCtxи тајмер.valueCtx: Подржава пренос вредности. Садржи основни контекст и кључ-вредност.
При отказу родитељског контекста, автоматски се отказују сви дечији. Ово омогућава ширење сигнала отказа или рокова кроз ланац позива.
Пример коришћења context.WithCancel:
package main
import (
"context"
"fmt"
"time"
)
func main() {
// Креирање коренског контекста и функције за отказивање
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // Гарантује отказивање при изласку из main
go func() {
select {
case <-ctx.Done(): // Чекамо на отказ контекста
fmt.Println("Задача отказана:", ctx.Err())
return
case <-time.After(5 * time.Second): // Или завршава за 5 секунди
fmt.Println("Задача извршена")
}
}()
// Отказивање контекста из другог места
time.Sleep(1 * time.Second)
fmt.Println("Отказивање контекста...")
cancel()
// Дамо време горутини да обради отказ
time.Sleep(100 * time.Millisecond)
}
Пример коришћења 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("Обрада захтева за User ID:", userID)
} else {
fmt.Println("User ID није пронађен у контексту")
}
}
func main() {
ctx := context.WithValue(context.Background(), userIDKey("UserID"), "12345")
processRequest(ctx)
}
Контексти су безбедни за рад са нитима и неизменљиви, што је важно за конкурентни код. Они нису намењени за пренос необрађених параметара функција, већ за мета-информације које утичу на извршавање процеса.