Einleitung: Warum Code Review in Go nicht nur ein Häkchen ist
\nCode Review ist kein bürokratischer Vorgang, sondern ein Schlüsselelement der Entwicklungskultur. In Go, mit seiner prägnanten Syntax und strengen Regeln, wird das Review oft zum ersten Filter, der Probleme frühzeitig aussortiert. Viele Teams, die auf Golang umsteigen, stellen fest, dass alte Gewohnheiten (z. B. aus Python oder PHP) nicht funktionieren: Go verzeiht weniger typbezogene Fehler, erfordert aber Aufmerksamkeit für Details.
\nIn der Praxis löst Code Review in Go drei Aufgaben: Teamschulung (Neulinge integrieren sich schneller in den Codestil), Qualitätssteigerung (Fehler und Antipattern finden) und Code-Konsistenz (damit das Projekt nicht zum "Flickenteppich" wird). Lassen Sie uns im Detail betrachten, worauf genau zu achten ist und wie Anmerkungen formuliert werden sollten.
\n\n1. Was zuerst prüfen: Von Syntax bis zu Fehlern
\nJedes Review beginnt mit grundlegenden Dingen. In Go gibt es einige "heiße Punkte", die automatisch oder manuell überprüft werden sollten.
\n\n1.1. Fehlerbehandlung (Error Handling)
\nGo verwendet keine Ausnahmen – Fehler werden als Werte zurückgegeben. Ein häufiges Problem: Der Entwickler ignoriert den zurückgegebenen Fehler mit _. Dies ist nur in seltenen Fällen zulässig (z. B. fmt.Println).
// Schlecht: Fehler wird ignoriert\nresp, _ := http.Get("https://api.example.com/data")\n\n// Gut: Fehler wird behandelt\nresp, err := http.Get("https://api.example.com/data")\nif err != nil {\n log.Printf("Daten konnten nicht abgerufen werden: %v", err)\n return err\n}\ndefer resp.Body.Close()\nWas prüfen:
\n- \n
- Werden alle Fehler behandelt (nicht einfach
_)? \n - Wird
deferzum Schließen von Ressourcen (Dateien, Verbindungen) verwendet? \n - Werden Fehler in Goroutinen "verschluckt"? \n
1.2. Benennung und Stil (Go Idioms)
\nGo erfordert Kürze: camelCase für private, PascalCase für exportierte Bezeichner. Vermeiden Sie "ungarische Notation" und lange Namen.
// Schlecht\nfunc GetUserDataFromDatabase(userID int) (*UserData, error)\n\n// Gut\nfunc GetUser(id int) (*User, error)\nRote Flaggen:
\n- \n
- Variablennamen wie
temp,data,val(zu allgemein). \n - Funktionen länger als 30-40 Zeilen (sollten aufgeteilt werden). \n
- Fehlende Kommentare zu exportierten Funktionen (dies ist eine Anforderung von
golint). \n
1.3. Goroutinen und Synchronisation
\nDies ist der schwierigste Teil. Fehler in nebenläufigem Code sind eine häufige Fehlerquelle in der Produktion.
\n// Schlecht: Datenrennen (Data Race)\nvar counter int\nfor i := 0; i < 100; i++ {\n go func() {\n counter++ // unsicher\n }()\n}\n\n// Gut: Mutex verwenden\nvar mu sync.Mutex\nvar counter int\nfor i := 0; i < 100; i++ {\n go func() {\n mu.Lock()\n counter++\n mu.Unlock()\n }()\n}\nWas prüfen:
\n- \n
- Gibt es
sync.Mutexoderatomicfür gemeinsame Daten? \n - Wurde vergessen, den Kanal zu schließen (
close(ch))? \n - "Lecken" Goroutinen (kein
selectmit Timeout)? \n
2. Architekturprüfungen: Von Interfaces bis zu Paketen
\nNach der grundlegenden Syntax betrachten wir die Code-Struktur. Go fördert Komposition, nicht Vererbung.
\n\n2.1. Interfaces: Klein und auf der Verbraucherseite
\nIn Go werden Interfaces implizit implementiert. Ein gutes Interface enthält 1-3 Methoden. Prüfen Sie, ob der Autor versucht, ein "allumfassendes" Interface zu erstellen.
\n// Schlecht: Riesiges Interface\ntype Storage interface {\n Save(data []byte) error\n Load(id string) ([]byte, error)\n Delete(id string) error\n List() ([]string, error)\n Connect() error\