Sobes.tech
Middle

Μίλησέ μου για τις περιπτώσεις χρήσης του πλαισίου στο Go.

sobes.tech AI

Απάντηση από AI

Το πλαίσιο στο Go χρησιμοποιείται για τη διαχείριση του κύκλου ζωής των αιτημάτων και τον έλεγχο της εκτέλεσης των goroutines. Οι κύριες περιπτώσεις χρήσης:

  • Ακύρωση: Επιτρέπει την ακύρωση της αλυσίδας goroutines που σχετίζονται με ένα συγκεκριμένο αίτημα. Για παράδειγμα, κατά το κλείσιμο της σύνδεσης ή λόγω χρονικού ορίου.
  • Χρονικό όριο: Ορίζει μια προθεσμία για την ολοκλήρωση της λειτουργίας. Αν η λειτουργία δεν ολοκληρωθεί εντός αυτής της προθεσμίας, το πλαίσιο ακυρώνεται. Αυτό αποτρέπει την ατελείωτη αναμονή.
  • Μεταφορά δεδομένων που σχετίζονται με το αίτημα: Επιτρέπει τη μεταφορά δεδομένων που σχετίζονται με ένα συγκεκριμένο αίτημα (π.χ. ID χρήστη, αναγνωριστικό παρακολούθησης) μέσω της αλυσίδας κλήσεων, χωρίς να αλλάζουν οι υπογραφές τους.

Παραδείγματα χρήσης:

  1. Ακύρωση με σήμα:

    package main
    
    import (
    	"context"
    	"fmt"
    	"time"
    )
    
    func worker(ctx context.Context, id int) {
    	for {
    		select {
    		case <-ctx.Done():
    			fmt.Printf("Εργάτης %d διακόπηκε\n", id)
    			return
    		default:
    			fmt.Printf("Εργάτης %d δουλεύει...\n", id)
    			time.Sleep(500 * time.Millisecond)
    		}
    	}
    }
    
    func main() {
    	ctx, cancel := context.WithCancel(context.Background())
    	defer cancel() // Εξασφαλίζει ακύρωση
    
    	go worker(ctx, 1)
    	go worker(ctx, 2)
    
    	time.Sleep(2 * time.Second)
    	cancel() // Ακυρώνει το πλαίσιο
    
    	time.Sleep(500 * time.Millisecond) // Δίνει χρόνο στις goroutines να τελειώσουν
    }
    
  2. Χρονικό όριο:

    package main
    
    import (
    	"context"
    	"fmt"
    	"time"
    )
    
    func longOperation(ctx context.Context) error {
    	select {
    	case <-time.After(3 * time.Second): // Προσομοίωση μακράς λειτουργίας
    		fmt.Println("Η λειτουργία ολοκληρώθηκε επιτυχώς")
    		return nil
    	case <-ctx.Done():
    		fmt.Println("Η λειτουργία ακυρώθηκε από το πλαίσιο:", ctx.Err())
    		return ctx.Err()
    	}
    }
    
    func main() {
    	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    	defer cancel()
    
    	err := longOperation(ctx)
    	if err != nil {
    		fmt.Println("Σφάλμα:", err)
    	}
    }
    
  3. Μεταφορά δεδομένων:

    package main
    
    import (
    	"context"
    	"fmt"
    )
    
    type UserKey string
    
    const userIDKey UserKey = "userID"
    
    func processRequest(ctx context.Context) {
    	userID := ctx.Value(userIDKey).(int)
    	fmt.Printf("Επεξεργασία αιτήματος για το χρήστη ID: %d\n", userID)
    	// Επιπλέον επεξεργασία αιτήματος με το userID
    }
    
    func main() {
    	ctx := context.WithValue(context.Background(), userIDKey, 123)
    	processRequest(ctx)
    }
    

Είναι σημαντικό να χρησιμοποιείτε context.Background() ή context.TODO() ως ριζικό πλαίσιο και να το περνάτε προς τα κάτω στη αλυσίδα των κλήσεων. Δεν πρέπει να αποθηκεύετε το πλαίσιο σε δομές δεδομένων αν δεν σχετίζεται άμεσα με τον κύκλο ζωής αυτής της δομής.