Fehlerbehandlung ist ein wichtiger Bestandteil der Softwareentwicklung, da sie uns hilft, Programme robuster und fehlertoleranter zu gestalten.
In Go werden Fehler in der Regel als Rückgabewerte von Funktionen behandelt. Dies ermöglicht eine explizite und einfache Fehlerprüfung. Hier ist ein grundlegendes Beispiel:
package main
import (
"errors"
"fmt"
)
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
func main() {
result, err := divide(4, 2)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Result:", result)
}
}In diesem Beispiel:
divide nimmt zwei Gleitkommazahlen
a und b und gibt entweder das Ergebnis der
Division oder einen Fehler zurück.b null ist, erzeugen wir einen neuen Fehler mit
errors.New("division by zero") und geben ihn zurück.main-Programm rufen wir divide auf und
überprüfen, ob ein Fehler aufgetreten ist. Wenn ja, drucken wir die
Fehlermeldung aus. Andernfalls drucken wir das Ergebnis aus.errors-BibliothekGo bietet das errors-Paket zur Erstellung und Verwaltung
von Fehlern. Das Paket enthält die Funktion errors.New, mit
der wir einfache Fehler erstellen können. Es gibt jedoch auch die
Möglichkeit, eigene Fehlerstrukturen zu definieren.
Hier ein Beispiel für die Erstellung eines benutzerdefinierten Fehlers:
package main
import (
"fmt"
)
type MyError struct {
Code int
Message string
}
func (e *MyError) Error() string {
return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}
func doSomething() error {
return &MyError{Code: 123, Message: "Something went wrong"}
}
func main() {
err := doSomething()
if err != nil {
fmt.Println(err)
}
}In diesem Beispiel:
MyError-Struktur mit den Feldern
Code und Message.Error implementiert die
error-Schnittstelle und gibt eine formatierte Fehlermeldung
zurück.doSomething gibt einen neuen
MyError zurück.main-Programm rufen wir doSomething auf
und drucken den Fehler aus, falls einer auftritt.In komplexen Programmen ist es oft notwendig, Fehler weiterzugeben. Dies kann durch Fehlerverkettung erreicht werden.
Hier ein Beispiel für die Fehlerverkettung:
package main
import (
"fmt"
"os"
)
func readFile(filename string) (string, error) {
file, err := os.Open(filename)
if err != nil {
return "", fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
data := make([]byte, 100)
_, err = file.Read(data)
if err != nil {
return "", fmt.Errorf("failed to read file: %w", err)
}
return string(data), nil
}
func main() {
content, err := readFile("example.txt")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("File content:", content)
}In diesem Beispiel:
readFile versucht, eine Datei zu öffnen
und ihren Inhalt zu lesen. Bei jedem Fehler verwenden wir
fmt.Errorf, um den Fehler zu umschließen und zusätzliche
Kontextinformationen hinzuzufügen.main-Programm rufen wir readFile auf
und drucken den Fehler aus, falls einer auftritt.Neben der expliziten Fehlerbehandlung bietet Go auch Mechanismen für
die Behandlung von Laufzeitfehlern durch panic und
recover.
Hier ein Beispiel für die Verwendung von panic und
recover:
package main
import "fmt"
func mightPanic() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong")
}
func main() {
fmt.Println("Starting main")
mightPanic()
fmt.Println("Ending main")
}In diesem Beispiel:
mightPanic löst eine Panik mit
panic("something went wrong") aus.defer-Funktionsaufruf fängt die Panik mit
recover ab und druckt eine Nachricht aus, wenn eine Panik
erkannt wird.main-Programm rufen wir mightPanic auf.
Der defer-Funktionsaufruf innerhalb von
mightPanic sorgt dafür, dass das Programm nicht abstürzt,
sondern die Panik abfängt und fortfährt.