Πώς είναι δομημένα τα πλαίσια στη γλώσσα Go;
sobes.tech AI
Απάντηση από AI
Το πλαίσιο (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()
// Δίνουμε χρόνο στο goroutine να επεξεργαστεί την ακύρωση
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)
}
Τα πλαίσια είναι ασφαλή για νήματα και αμετάβλητα, κάτι σημαντικό για τον ανταγωνιστικό κώδικα. Δεν προορίζονται για τη μεταφορά ακατέργαστων παραμέτρων λειτουργίας, αλλά μάλλον για μετα-πληροφορίες που επηρεάζουν την εκτέλεση της διαδικασίας.