Go-Code-Review: Was ein Senior sagt und warum Ihr Code nicht durchkommt

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Ihr Go-Code: Von „funktioniert“ bis „akzeptiert“

\n\n

Sie haben Code in Go geschrieben. Er kompiliert. Die Tests sind grün. Sie sind stolz. Doch dann kommt das Code-Review vom Senior-Entwickler, und fünf Minuten später ist Ihr Pull-Request mit roten Kommentaren übersät. Kommt Ihnen das bekannt vor?

\n\n

Go ist eine Sprache, bei der „Einfachheit“ trügerisch ist. Hinter der scheinbaren Leichtigkeit verbergen sich Dutzende von Fallstricken, die ein erfahrenes Auge sofort erkennt. In diesem Artikel analysieren wir die häufigsten Anmerkungen, die Seniors bei Go-Code-Reviews hinterlassen. Sie erfahren nicht nur, was falsch ist, sondern auch, wie Sie es beheben, damit Ihr Code beim ersten Mal durch das Review kommt.

\n\n

Los geht's mit der Analyse typischer Fehler im Golang-Code-Review.

\n\n

1. Fehlerbehandlung: Nicht nur if err != nil

\n\n

Problem: Ignorieren von Fehlern oder „nacktes“ return

\n\n

Das häufigste Problem bei Anfängern ist eine nicht ausreichend informative Fehlerbehandlung. Einfach den Fehler nach oben zu reichen, ist nur die halbe Miete. Ein Senior wird immer fragen: „Was ist schiefgelaufen? Wo?“.

\n\n
// Schlecht: Der Senior sagt „füge Kontext hinzu“\nfunc ReadConfig(path string) (*Config, error) {\n    data, err := os.ReadFile(path)\n    if err != nil {\n        return nil, err // ❌ Kein Kontext\n    }\n    // ...\n}\n
\n\n

Der richtige Ansatz ist, Fehler mit fmt.Errorf und dem Platzhalter %w zu umschließen (für spätere Prüfungen mit errors.Is oder errors.As).

\n\n
// Gut: Der Senior nickt zustimmend\nfunc ReadConfig(path string) (*Config, error) {\n    data, err := os.ReadFile(path)\n    if err != nil {\n        return nil, fmt.Errorf("read config file %s: %w", path, err) // ✅ Kontext + Kette\n    }\n    // ...\n}\n
\n\n

Problem: Sich wiederholendes if err != nil

\n\n

Go ist bekannt für seine Wortlastigkeit bei der Fehlerbehandlung. Aber das bedeutet nicht, dass man sich mit Copy-Paste abfinden muss. Ein Senior wird vorschlagen, wiederholte Prüfungen in Helfer auszulagern oder das „errgroup“-Pattern für Goroutinen zu verwenden.

\n\n
    \n
  • Machen Sie das nicht: 10 Mal hintereinander if err != nil { return ... } in einer Funktion ist in Ordnung, aber wenn sich das Muster in verschiedenen Funktionen wiederholt, ist es Zeit für ein Refactoring.
  • \n
  • Tipp des Seniors: Verwenden Sie defer zum Schließen von Ressourcen und zur Überprüfung von Schließfehlern (ja, file.Close() gibt ebenfalls einen Fehler zurück).
  • \n
\n\n

2. Nebenläufigkeit: Datenrennen und falsche Kanäle

\n\n

Problem: Zugriff auf eine gemeinsame Variable ohne Synchronisation

\n\n

Go ist eine Sprache, in der Goroutinen billig sind, Datenrennen jedoch teuer. Ein Senior wird sofort bemerken, wenn Sie ohne Mutex aus mehreren Goroutinen in eine Map oder ein Slice schreiben.

\n\n
// Schlecht: Data Race\nvar counter int\nfor i := 0; i < 100; i++ {\n    go func() {\n        counter++ // ❌ Rennen!\n    }()\n}\n
\n\n

Lösung: Verwenden Sie sync.Mutex oder Atomik-Operationen. Aber der Senior wird sagen: „Wäre es nicht einfacher, Kanäle zu verwenden?“.

\n\n
// Gut: Kanäle zur Synchronisation\nch := make(chan int, 100)\nfor i := 0; i < 100; i++ {\n    go func() {\n        ch <- 1\n    }()\n}\nvar counter int\nfor i := 0; i < 100; i++ {\n    counter += <-ch // ✅ Keine Rennen\n}\n
\n\n

Problem: Goroutine-Leck

\n\n

Vergessen, einen Kanal zu schließen? Die Goroutine hängt für immer fest. Ein Senior wird beim Go-Code-Review auf jeden Fall prüfen, ob bei Ihnen eine Goroutine ohne select mit ctx.Done() „hängt“.

\n\n
// Schlecht: Goroutine könnte ewig hängen\ngo func() {\n    for msg := range ch {\n        process(msg)\n    }\n}()\n// Wenn ch nie geschlossen wird – Speicherleck\n
\n\n

Das richtige Muster ist, immer context.Context zu übergeben und auf das Abbruchsignal zu hören.

\n\n
// Gut: Schutz vor Leck\ngo func(ctx context.Context) {\n    for {\n        select {\n        case msg, ok := <-ch:\n            if !ok {\n                return // Kanal geschlossen\n            }\n            process(msg)                

Blogs

Buchempfehlungen