En aquest tema, aprendrem com crear i gestionar errors personalitzats en Go. La gestió d'errors és una part crucial del desenvolupament de programari, ja que permet identificar i manejar situacions inesperades de manera controlada. Go proporciona mecanismes per crear errors personalitzats que poden contenir informació addicional sobre el problema que ha ocorregut.

Continguts

Introducció als Errors Personalitzats

Els errors personalitzats són errors definits per l'usuari que poden proporcionar informació més detallada sobre una situació d'error específica. A Go, els errors es representen mitjançant el tipus error, que és una interfície amb un únic mètode:

type error interface {
    Error() string
}

Creació d'Errors Personalitzats

Per crear un error personalitzat, podem definir un nou tipus que implementi la interfície error. Això es fa generalment definint una estructura que contingui informació addicional sobre l'error i implementant el mètode Error().

Exemple

package main

import (
    "fmt"
)

// Definim un nou tipus d'error personalitzat
type MyCustomError struct {
    Code    int
    Message string
}

// Implementem el mètode Error() per al nostre tipus d'error personalitzat
func (e *MyCustomError) Error() string {
    return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}

func main() {
    // Creem una instància del nostre error personalitzat
    err := &MyCustomError{
        Code:    404,
        Message: "Resource not found",
    }

    // Utilitzem l'error
    fmt.Println(err)
}

En aquest exemple, hem creat un tipus d'error personalitzat MyCustomError que conté un codi d'error i un missatge. El mètode Error() retorna una cadena que representa l'error.

Gestió d'Errors Personalitzats

Un cop hem creat un error personalitzat, podem utilitzar-lo en les nostres funcions i gestionar-lo de manera adequada. Això implica retornar l'error des de les funcions i manejar-lo en el codi que crida aquestes funcions.

Exemple

package main

import (
    "fmt"
)

// Definim un nou tipus d'error personalitzat
type MyCustomError struct {
    Code    int
    Message string
}

// Implementem el mètode Error() per al nostre tipus d'error personalitzat
func (e *MyCustomError) Error() string {
    return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}

// Funció que pot retornar un error personalitzat
func doSomething() error {
    // Simulem una situació d'error
    return &MyCustomError{
        Code:    500,
        Message: "Internal server error",
    }
}

func main() {
    // Cridem la funció que pot retornar un error
    err := doSomething()
    if err != nil {
        // Gestionem l'error
        fmt.Println("An error occurred:", err)
    }
}

En aquest exemple, la funció doSomething retorna un error personalitzat. En el main, cridem aquesta funció i gestionem l'error si es produeix.

Exemples Pràctics

Exemple 1: Error de Validació

package main

import (
    "fmt"
)

// Definim un error de validació personalitzat
type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("Validation error on field '%s': %s", e.Field, e.Message)
}

func validateInput(input string) error {
    if input == "" {
        return &ValidationError{
            Field:   "input",
            Message: "Input cannot be empty",
        }
    }
    return nil
}

func main() {
    err := validateInput("")
    if err != nil {
        fmt.Println("Error:", err)
    }
}

Exemple 2: Error de Connexió

package main

import (
    "fmt"
)

// Definim un error de connexió personalitzat
type ConnectionError struct {
    URL     string
    Message string
}

func (e *ConnectionError) Error() string {
    return fmt.Sprintf("Connection error to '%s': %s", e.URL, e.Message)
}

func connectToServer(url string) error {
    // Simulem una situació d'error de connexió
    return &ConnectionError{
        URL:     url,
        Message: "Unable to reach the server",
    }
}

func main() {
    err := connectToServer("http://example.com")
    if err != nil {
        fmt.Println("Error:", err)
    }
}

Exercicis Pràctics

Exercici 1: Error de Divisió per Zero

Crea un error personalitzat per gestionar la divisió per zero en una funció que divideix dos nombres.

Solució

package main

import (
    "fmt"
)

// Definim un error de divisió per zero personalitzat
type DivisionByZeroError struct {
    Message string
}

func (e *DivisionByZeroError) Error() string {
    return e.Message
}

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, &DivisionByZeroError{
            Message: "Cannot divide by zero",
        }
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Result:", result)
    }
}

Exercici 2: Error de Fitxer No Trobat

Crea un error personalitzat per gestionar la situació en què un fitxer no es troba.

Solució

package main

import (
    "fmt"
)

// Definim un error de fitxer no trobat personalitzat
type FileNotFoundError struct {
    Filename string
    Message  string
}

func (e *FileNotFoundError) Error() string {
    return fmt.Sprintf("File '%s' not found: %s", e.Filename, e.Message)
}

func readFile(filename string) error {
    // Simulem una situació d'error de fitxer no trobat
    return &FileNotFoundError{
        Filename: filename,
        Message:  "The file does not exist",
    }
}

func main() {
    err := readFile("nonexistent.txt")
    if err != nil {
        fmt.Println("Error:", err)
    }
}

Conclusió

En aquesta secció, hem après com crear i gestionar errors personalitzats en Go. Els errors personalitzats ens permeten proporcionar informació més detallada sobre les situacions d'error, cosa que facilita la depuració i el maneig d'errors en les nostres aplicacions. Hem vist exemples pràctics i hem realitzat exercicis per reforçar els conceptes apresos. En la següent secció, explorarem el concepte de panic i recover per gestionar errors crítics.

© Copyright 2024. Tots els drets reservats