Sobes.tech
Middle

Πώς είναι δομημένα τα πλαίσια στη γλώσσα 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)
}

Τα πλαίσια είναι ασφαλή για νήματα και αμετάβλητα, κάτι σημαντικό για τον ανταγωνιστικό κώδικα. Δεν προορίζονται για τη μεταφορά ακατέργαστων παραμέτρων λειτουργίας, αλλά μάλλον για μετα-πληροφορίες που επηρεάζουν την εκτέλεση της διαδικασίας.