Sobes.tech
Junior

Kas yra kontekstas Go?

sobes.tech AI

Atsakymas iš AI

Kontekstas (context.Context) Go kalboje yra objektas, kuris nešioja terminą, atšaukimo signalą (cancellation signal) ir duomenis, būdingus užklausai. Jis naudojamas gorutinų gyvavimo ciklo valdymui ir informacijos perdavimui tarp jų vykdymo metu.

Pagrindinės savybės:

  • Saugus kelių gijų: Gali būti saugiai perduodamas tarp gorutinų.
  • Neįmanoma keisti: Sukūręs, Context negali būti pakeistas. Paveldimi kontekstai kuriami remiantis tėvų kontekstu.
  • Hierarchinis: Kontekstai sudaro medį su šaknimi (context.Background() arba context.TODO()). Tėvo konteksto atšaukimas sukelia visų vaikų atšaukimą.

context paketo pagrindinės funkcijos:

  • context.Background(): Tuščias kontekstas, dažniausiai naudojamas pagrindinėje funkcijoje, viršutiniuose užklausose arba testavimui. Niekada nėra atšaukiamas.
  • context.TODO(): Taip pat tuščias kontekstas. Naudojamas kaip laikinas pakaitalas, kai nežinoma, kurį kontekstą naudoti, arba kai funkcionalumas dar nėra įgyvendintas.
  • context.WithCancel(parent Context): Grąžina naują vaikų kontekstą ir atšaukimo funkciją. Iškvietus atšaukimo funkciją, šis kontekstas ir visi jo vaikai atšaukiami.
  • context.WithDeadline(parent Context, deadline time.Time): Grąžina vaikų kontekstą, kuris automatiškai atšaukiamas, kai pasiekiamas nurodytas laikas. Taip pat grąžina atšaukimo funkciją rankiniam atšaukimui.
  • context.WithTimeout(parent Context, timeout time.Duration): Tas pats kaip WithDeadline, bet su trukmės nurodymu.
  • context.WithValue(parent Context, key, val interface{}): Grąžina vaikų kontekstą su priskirta reikšme pagal raktą.

Naudojimas:

  • Operacijų atšaukimas: Pavyzdžiui, HTTP užklausos laiko limitas arba ilgos operacijos nutraukimas.
  • Duomenų perdavimas: Pavyzdžiui, užklausos ID žurnalui, autentifikacijos informacija.

context.WithTimeout pavyzdys:

package main

import (
	"context"
	"fmt"
	"time"
)

func longRunningOperation(ctx context.Context, resultChan chan string) {
	select {
	case <-time.After(3 * time.Second):
		// Operacija sėkmingai baigta
		resultChan <- "Operation completed"
	case <-ctx.Done():
		// Kontekstas buvo atšauktas
		err := ctx.Err() // Gauname atšaukimo priežastį
		resultChan <- fmt.Sprintf("Operation cancelled: %v", err)
	}
}

func main() {
	// Sukuriamas kontekstas su 2 sekundžių laiko limitu
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel() // Garantuoja atšaukimo funkcijos iškvietimą

	resultChan := make(chan string, 1)

	go longRunningOperation(ctx, resultChan)

	// Laukiame rezultato arba atšaukimo
	select {
	case res := <-resultChan:
		fmt.Println(res)
	case <-ctx.Done():
		fmt.Printf("Main context done: %v\n", ctx.Err())
	}

	// Šiek tiek palaukiame, kad gorutina galėtų užbaigti, jei buvo atšaukta
	time.Sleep(1 * time.Second)
}

Šiame pavyzdyje longRunningOperation tikrina konteksto atšaukimo būseną. Jei pagrindinio konteksto (2 sekundės) laiko limitas pasibaigia anksčiau nei operacija (3 sekundės), gorutina gauna signalą per ctx.Done() ir baigiasi.