Junior
Τι είναι το πλαίσιο στο Go;
sobes.tech AI
Απάντηση από AI
Το πλαίσιο (context.Context) στο Go είναι ένα αντικείμενο που μεταφέρει μια προθεσμία, ένα σήμα ακύρωσης και δεδομένα που είναι συγκεκριμένα για το αίτημα. Χρησιμοποιείται για τη διαχείριση του κύκλου ζωής των goroutines και για τη μεταφορά πληροφοριών μεταξύ αυτών κατά την εκτέλεση ενός αιτήματος/λειτουργίας.
Βασικά χαρακτηριστικά:
- Ασφαλές για ταυτόχρονες διεργασίες: Μπορεί να μεταφερθεί με ασφάλεια μεταξύ goroutines.
- Αμετάβλητο: Μόλις δημιουργηθεί, ένα
Contextδεν μπορεί να αλλάξει. Οι παράγωγοι contexts δημιουργούνται βάσει του γονέα. - Ιεραρχικό: Τα contexts σχηματίζουν ένα δέντρο με ρίζα (
context.Background()ήcontext.TODO()). Η ακύρωση του γονικού context οδηγεί στην ακύρωση όλων των παιδιών του.
Βασικές λειτουργίες του πακέτου context:
context.Background(): Κενό context, συνήθως χρησιμοποιείται στη συνάρτηση main, σε αιτήματα υψηλού επιπέδου ή κατά τη δοκιμή. Ποτέ δεν ακυρώνεται.context.TODO(): Επίσης ένα κενό context. Χρησιμοποιείται ως placeholder όταν δεν είναι γνωστό ποιο context να χρησιμοποιηθεί ή αν η λειτουργικότητα του context δεν έχει ακόμη υλοποιηθεί.context.WithCancel(parent Context): Επιστρέφει ένα νέο παιδικό context και μια λειτουργία ακύρωσης. Η κλήση αυτής της λειτουργίας ακυρώνει αυτό το context και όλα τα παιδικά contexts του.context.WithDeadline(parent Context, deadline time.Time): Επιστρέφει ένα παιδικό context που ακυρώνεται αυτόματα όταν φτάσει η καθορισμένη ώρα. Επίσης επιστρέφει μια λειτουργία ακύρωσης για χειροκίνητη ακύρωση.context.WithTimeout(parent Context, timeout time.Duration): Το ίδιο με τοWithDeadline, αλλά με διάρκεια.context.WithValue(parent Context, key, val interface{}): Επιστρέφει ένα παιδικό context με μια τιμή που έχει ανατεθεί σε ένα κλειδί.
Εφαρμογές:
- Ακύρωση λειτουργιών: Για παράδειγμα, timeout σε ένα αίτημα HTTP ή διακοπή μιας μακράς λειτουργίας.
- Μεταφορά δεδομένων: Για παράδειγμα, ID αιτήματος για καταγραφή, πληροφορίες αυθεντικοποίησης.
Παράδειγμα χρήσης του context.WithTimeout:
package main
import (
"context"
"fmt"
"time"
)
func longRunningOperation(ctx context.Context, resultChan chan string) {
select {
case <-time.After(3 * time.Second):
// Η λειτουργία ολοκληρώθηκε με επιτυχία
resultChan <- "Λειτουργία ολοκληρώθηκε"
case <-ctx.Done():
// Το context ακυρώθηκε
err := ctx.Err() // Λαμβάνουμε τον λόγο ακύρωσης
resultChan <- fmt.Sprintf("Λειτουργία ακυρώθηκε: %v", err)
}
}
func main() {
// Δημιουργούμε ένα context με timeout 2 δευτερολέπτων
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() // Εξασφαλίζουμε την κλήση της λειτουργίας ακύρωσης
resultChan := make(chan string, 1)
go longRunningOperation(ctx, resultChan)
// Περιμένουμε το αποτέλεσμα ή την ακύρωση
select {
case res := <-resultChan:
fmt.Println(res)
case <-ctx.Done():
fmt.Printf("Το κύριο context ολοκληρώθηκε: %v\n", ctx.Err())
}
// Περιμένουμε λίγο για να τελειώσει η goroutine αν ακυρώθηκε
time.Sleep(1 * time.Second)
}
Σε αυτό το παράδειγμα, η longRunningOperation ελέγχει αν το context ακυρώθηκε. Αν η χρονική λήξη του κύριου context (2 δευτερόλεπτα) λήξει πριν ολοκληρωθεί η ίδια η λειτουργία (3 δευτερόλεπτα), η goroutine λαμβάνει το σήμα ακύρωσης μέσω του ctx.Done() και τερματίζει.