Golang ou Go dispose d'un mécanisme robuste de gestion des erreurs qui fait partie intégrante de la conception du langage. Bien que Go fournisse des types d'erreurs intégrés, il existe des situations dans lesquelles vous pourriez avoir besoin de plus de contrôle et de contexte dans votre gestion des erreurs.
C'est là qu'intervient la création d'erreurs personnalisées. Les erreurs personnalisées peuvent vous fournir des messages d'erreur plus informatifs et peuvent être utilisées pour catégoriser différents types d'erreurs dans votre application.
Dans cet article, nous explorerons comment créer et utiliser efficacement des erreurs personnalisées dans Golang.
Dans Go, le type d'erreur est une interface intégrée qui ressemble à ceci :
type error interface { Error() string }
Tout type qui implémente la méthode Error() avec un type de retour chaîne satisfait cette interface et peut être considéré comme une erreur. C'est simple mais puissant car cela vous permet de créer des types d'erreur personnalisés en implémentant simplement cette méthode.
Voici un exemple rapide de gestion des erreurs de base dans Go :
package main import ( "errors" "fmt" ) func main() { err := doSomething() if err != nil { fmt.Println("Error:", err) } } func doSomething() error { return errors.New("something went wrong") }
Cet exemple utilise la fonction error.New pour créer une erreur de base. Bien que cela soit utile pour les cas simples, il n'a pas la capacité de fournir plus de contexte ou de distinguer les différents types d'erreurs.
Les erreurs personnalisées sont essentielles lorsque vous avez besoin de messages d'erreur plus descriptifs ou lorsque vous souhaitez gérer différemment différents types d'erreurs. Par exemple, vous souhaiterez peut-être renvoyer un type d'erreur spécifique lorsqu'un fichier est introuvable et un autre type lorsqu'un fichier est corrompu. Les erreurs personnalisées peuvent également contenir des données supplémentaires, ce qui facilite le débogage et fournit des informations plus détaillées à l'appelant.
Pour créer une erreur personnalisée dans Go, vous définissez un nouveau type qui implémente la méthode Error(). Passons en revue un exemple.
Voici comment créer une erreur personnalisée simple :
package main import ( "fmt" ) type MyError struct { Code int Message string } func (e *MyError) Error() string { return fmt.Sprintf("Code %d: %s", e.Code, e.Message) } func main() { err := doSomething() if err != nil { fmt.Println("Error:", err) } } func doSomething() error { return &MyError{ Code: 404, Message: "Resource not found", } }
Dans cet exemple, MyError est un type d'erreur personnalisé qui comprend un code et un message. La méthode Error() les formate en chaîne, ce qui facilite l'impression ou l'enregistrement de l'erreur.
Parfois, il est utile de comparer directement les erreurs. C'est là qu'interviennent les erreurs sentinelles. Une erreur sentinelle est une variable prédéfinie et exportée qui représente une erreur spécifique.
package main import ( "errors" "fmt" ) var ErrNotFound = errors.New("resource not found") func main() { err := doSomething() if errors.Is(err, ErrNotFound) { fmt.Println("Error:", err) } } func doSomething() error { return ErrNotFound }
Bien que cette approche soit simple, la combinaison de valeurs sentinelles avec des types d'erreurs personnalisés peut être encore plus puissante, permettant à la fois une comparaison des erreurs et des données d'erreur riches.
Go 1.13 a introduit la fonction fmt.Errorf avec le verbe %w, qui vous permet d'envelopper les erreurs, en ajoutant plus de contexte tout en préservant l'erreur d'origine.
package main import ( "errors" "fmt" ) var ErrNotFound = errors.New("resource not found") func main() { err := doSomething() if err != nil { fmt.Println("Error:", err) if errors.Is(err, ErrNotFound) { fmt.Println("The resource was not found.") } } } func doSomething() error { err := fetchResource() if err != nil { return fmt.Errorf("failed to do something: %w", err) } return nil } func fetchResource() error { return ErrNotFound }
Cela vous permet de rechercher des erreurs spécifiques et également de conserver une pile d'erreurs qui donne plus de contexte sur ce qui n'a pas fonctionné.
Go fournit également un moyen d'extraire l'erreur encapsulée à l'aide de la méthode Unwrap(). En implémentant cette méthode dans vos types d'erreurs personnalisés, vous pouvez permettre un déballage plus approfondi des erreurs.
package main import ( "errors" "fmt" ) type MyError struct { Code int Message string Err error } func (e *MyError) Error() string { return fmt.Sprintf("Code %d: %s", e.Code, e.Message) } func (e *MyError) Unwrap() error { return e.Err } func main() { err := doSomething() if err != nil { fmt.Println("Error:", err) if errors.Is(err, ErrNotFound) { fmt.Println("The resource was not found.") } } } var ErrNotFound = errors.New("resource not found") func doSomething() error { err := fetchResource() if err != nil { return &MyError{ Code: 500, Message: "Something went wrong", Err: err, } } return nil } func fetchResource() error { return ErrNotFound }
Ici, MyError a une méthode Unwrap() qui renvoie l'erreur encapsulée. Cela permet une inspection et un traitement plus approfondis de l'erreur sous-jacente.
Go fournit également un moyen d'extraire l'erreur avec la méthode erreurs.As. En implémentant cette méthode dans vos types d'erreur personnalisés, vous pouvez vérifier le type d'erreur et également récupérer les valeurs d'erreur personnalisées.
package main import ( "errors" "fmt" ) type MyError struct { Code int Message string Err error } func (e *MyError) Error() string { return fmt.Sprintf("Code %d: %s: %v", e.Code, e.Message, e.Err) } func main() { err := doSomething() var mErr *MyError // another way to initialize custom error // mErr := &MyError{} if errors.As(err, &mErr) { fmt.Println("Error:", mErr) } } // doSomething attempts to fetch a resource and returns an error if it fails. // If the error is ErrNotFound, it is wrapped in a MyError with a code of 500. func doSomething() error { err := fetchResource() if err != nil { return &MyError{ Code: 500, Message: "Something went wrong", Err: err, } } return nil } var ErrNotFound = errors.New("resource not found") func fetchResource() error { return ErrNotFound }
Utilisez les erreurs personnalisées avec parcimonie : Les erreurs personnalisées sont puissantes mais peuvent ajouter de la complexité. Utilisez-les lorsqu'ils offrent des avantages significatifs, comme une meilleure catégorisation des erreurs ou un contexte supplémentaire.
Exploiter l'encapsulation et le déballage : Encapsuler les erreurs avec un contexte supplémentaire et les déballer plus tard est une bonne pratique qui améliore le débogage des erreurs.
Documentez vos types d'erreur : Assurez-vous que toutes les erreurs personnalisées sont bien documentées afin que leur objectif et leur utilisation soient clairs.
Préférer les valeurs d'erreur pour la comparaison : Lorsque vous devez comparer des erreurs, envisagez d'utiliser des valeurs d'erreur prédéfinies (erreurs sentinelles) pour plus de cohérence et de clarté.
Les erreurs personnalisées dans Go offrent un moyen flexible et puissant de gérer les erreurs dans vos applications. En créant vos propres types d'erreurs, en encapsulant les erreurs pour un contexte supplémentaire et en les déballant pour une inspection plus approfondie, vous pouvez créer des mécanismes de gestion des erreurs robustes et maintenables. Cela aide non seulement au débogage, mais améliore également la qualité globale de votre code Go.
Choisissez votre stratégie avec les erreurs et utilisez les erreurs cohérentes dans l'ensemble du projet.
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3