Menu
Coddy logo textTech

Rozpakowywanie za pomocą `errors.Is`

Część sekcji Logika i przepływ sterowania ścieżki GO w Coddy. Lekcja 40 z 68.

Podczas pracy z opakowanymi błędami potrzebujesz sposobu na sprawdzenie, czy określony błąd występuje gdziekolwiek w łańcuchu błędów. Funkcja errors.Is zapewnia taką możliwość, pozwalając identyfikować błędy wartownicze, nawet jeśli zostały opakowane wielokrotnie.

Funkcja errors.Is przyjmuje dwa parametry: błąd, który chcesz sprawdzić, oraz błąd docelowy, którego szukasz. Zwraca true, jeśli błąd docelowy zostanie znaleziony w dowolnym miejscu łańcucha błędów:

var ErrNotFound = errors.New("not found")

wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)

if errors.Is(wrappedErr, ErrNotFound) {
    fmt.Println("This is a not found error")
}

To nowoczesny, zalecany sposób sprawdzania konkretnych błędów w Go. W przeciwieństwie do porównywania ciągów znaków lub bezpośredniego sprawdzania równości, errors.Is działa poprawnie w przypadku opakowanych błędów i podąża za łańcuchem błędów, aby znaleźć dopasowania. Dzięki temu obsługa błędów jest solidna i niezawodna, nawet gdy błędy przechodzą przez wiele warstw aplikacji.

challenge icon

Wyzwanie

Łatwy

Zbuduj system monitorowania połączeń z bazą danych, który używa errors.Is do identyfikowania określonych błędów połączenia w łańcuchach opakowanych błędów. To wyzwanie pokazuje, jak używać errors.Is do wykrywania błędów wartowniczych, nawet gdy zostały opakowane dodatkowym kontekstem na wielu warstwach aplikacji.

Otrzymasz dwa dane wejściowe:

  • Ciąg zawierający szczegóły operacji na bazie danych w formacie "database_name,operation,error_type" (np. "users_db,connect,connection_timeout")
  • Ciąg zawierający kontekst aplikacji w formacie "service_name,retry_count" (np. "AuthService,3")

Twoim zadaniem jest:

  1. Zdefiniować trzy błędy wartownicze za pomocą errors.New():
    • ErrConnectionTimeout z komunikatem "connection timeout"
    • ErrConnectionRefused z komunikatem "connection refused"
    • ErrDatabaseNotFound z komunikatem "database not found"
  2. Przeanalizować pierwsze dane wejściowe, dzieląc je po przecinkach, aby uzyskać nazwę bazy danych, operację i typ błędu
  3. Przeanalizować drugie dane wejściowe, dzieląc je po przecinkach, aby uzyskać nazwę usługi i liczbę ponownych prób
  4. Utworzyć pierwotny błąd na podstawie typu błędu:
    • Jeśli typ błędu to "connection_timeout": użyć ErrConnectionTimeout
    • Jeśli typ błędu to "connection_refused": użyć ErrConnectionRefused
    • Jeśli typ błędu to "database_not_found": użyć ErrDatabaseNotFound
    • W przypadku każdego innego typu błędu: użyć errors.New("unknown database error")
  5. Utworzyć opakowany błąd na poziomie bazy danych za pomocą fmt.Errorf i %w: "failed to [operation] database [database_name]: %w"
  6. Utworzyć opakowany błąd na poziomie usługi: "[service_name] database operation failed after [retry_count] retries: %w"
  7. Użyć errors.Is, aby sprawdzić, czy końcowy opakowany błąd odpowiada każdemu z błędów wartowniczych, i wyświetlić wyniki:
    • "Checking for connection timeout: [true/false]"
    • "Checking for connection refused: [true/false]"
    • "Checking for database not found: [true/false]"
  8. Wyświetlić łańcuch błędów:
    • "Error Chain:"
    • "Original: [original_error_message]"
    • "Database level: [database_level_error_message]"
    • "Service level: [service_level_error_message]"
  9. Wyświetlić analizę błędu:
    • "Error Analysis:"
    • "Database: [database_name]"
    • "Operation: [operation]"
    • "Service: [service_name]"
    • "Retries: [retry_count]"
    • "Error type detected: [detected_error_type]", gdzie detected_error_type to jedna z wartości "Connection Timeout", "Connection Refused", "Database Not Found" lub "Unknown Error"

Użyj pakietu strings, aby dzielić ciągi wejściowe po przecinkach, pakietu errors do obsługi błędów wartowniczych i errors.Is, a także pakietu fmt do opakowywania błędów. To wyzwanie pokazuje, jak errors.Is umożliwia niezawodne identyfikowanie błędów, które działa poprawnie również w przypadku opakowanych błędów, dzięki czemu jest niezbędne do niezawodnej obsługi błędów w złożonych aplikacjach.

Spróbuj swoich sił

package main

import (
	"errors"
	"fmt"
	"strings"
)

func main() {
	// Wczytaj dane wejściowe
	var dbOperation string
	var appContext string
	fmt.Scanln(&dbOperation)
	fmt.Scanln(&appContext)
	
	// Przetwórz dane wejściowe
	dbParts := strings.Split(dbOperation, ",")
	databaseName := dbParts[0]
	operation := dbParts[1]
	errorType := dbParts[2]
	
	contextParts := strings.Split(appContext, ",")
	serviceName := contextParts[0]
	retryCount := contextParts[1]
	
	// TODO: Napisz swój kod poniżej
	// 1. Zdefiniuj trzy błędy wartownicze za pomocą errors.New()
	// 2. Utwórz pierwotny błąd na podstawie typu błędu
	// 3. Utwórz opakowany błąd na poziomie bazy danych za pomocą fmt.Errorf i %w
	// 4. Utwórz opakowany błąd na poziomie usługi
	// 5. Użyj errors.Is, aby sprawdzić każdy z błędów wartowniczych
	// 6. Wyświetl wyniki i łańcuch błędów
	
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Logika i przepływ sterowania

Poćwicz samodzielnie: Kompilator Go online