- Mit Go 1.26 wird der vollständig neu geschriebene Befehl
go fix eingeführt, der Code mithilfe aktueller Sprach- und Bibliotheksfunktionen automatisch verbessern kann
- Das Tool erkennt über Dutzende Analyzer Code-Muster und wendet verschiedene Modernizer wie
minmax, rangeint und stringscut an, um wiederholten oder veralteten Code in moderne Formen zu überführen
- Zur Unterstützung der neuen Funktion
new(expr) wurde der Analyzer newexpr hinzugefügt, der Hilfsfunktionen wie newInt automatisch vereinfachen kann
- Mehrfaches Ausführen von
go fix erzeugt Synergieeffekte: Unterschiedliche Analyzer können nacheinander Verbesserungen vorschlagen; außerdem sind automatische Zusammenführung bei Konflikten und das Entfernen unnötiger Imports enthalten
- Das Go-Team plant künftig eine Erweiterung über ein „Self-service“-Analyseparadigma, damit Entwickler Modernizer für ihre eigenen APIs definieren und verteilen können
Überblick über den Befehl go fix
- In Go 1.26 wurde
go fix vollständig neu implementiert und bietet nun die automatische Umwandlung von Codebasen in einen aktuellen Go-Stil
- Mit dem Befehl
go fix ./... werden alle Pakete unterhalb des aktuellen Verzeichnisses angepasst
- Mit der Option
-diff lassen sich Änderungen vorab anzeigen
- Die Liste der registrierten Analyzer lässt sich mit
go tool fix help anzeigen und umfasst verschiedene Transformationsregeln wie any, forvar, mapsloop und minmax
- Um nur einen bestimmten Analyzer auszuführen, wird ein Flag wie
-any verwendet; zum Ausschließen -any=false
- Unter Berücksichtigung plattformspezifischer Code-Unterschiede ist eine mehrfache Ausführung für verschiedene
GOOS-/GOARCH-Kombinationen möglich
Modernizer — Werkzeuge zur Code-Modernisierung
- Seit der Einführung von Generics ab Go 1.18 ist das Potenzial zur Vereinfachung von Code deutlich gestiegen
- Beispiel: Sammeln von Map-Schlüsseln mit
maps.Keys, Aufteilen von Strings mit strings.Cut
- Um das Problem zu beheben, dass LLM-basierte Codegenerierungs-Tools veraltete Muster beibehalten, wird die Notwendigkeit betont, Open-Source-Code mit aktuellen Go-Idiomen zu aktualisieren
- Die in
go fix und gopls enthaltenen Modernizer verbessern Lesbarkeit und Lerneffekt des Codes
- Beispielhafte Modernizer:
- minmax: Ersetzt
if-Anweisungen durch min-/max-Funktionen
- rangeint: Wandelt dreiteilige
for-Schleifen in range-over-int um
- stringscut: Vereinfacht auf
strings.Index basierenden Code mit strings.Cut
Die Funktion new(expr) in Go 1.26
- Die Funktion
new wurde erweitert, sodass sie Wertargumente zulässt und eine Initialisierung in der Form new("go1.26") ermöglicht
- Der Analyzer
newexpr findet Hilfsfunktionen wie newInt, vereinfacht sie zu return new(x) und ersetzt Aufrufstellen durch new(expr)
- Die Anwendung erfolgt nur, wenn die minimale Go-Version erfüllt ist (z. B. mit der Direktive
go 1.26)
- Mit dem Befehl
$ go fix -newexpr ./... lässt sich dies auf die gesamte Codebasis anwenden
- Nach der Anwendung können unnötige Hilfsfunktionen mit dem Tool
deadcode identifiziert werden
Synergien und Konfliktbehandlung
- Eine einzelne Änderung kann Synergieeffekte erzeugen und neue Möglichkeiten für weitere Änderungen schaffen
- Beispiel: Nach Anwendung von
minmax werden zusätzliche Transformationen vorgeschlagen
- Möglich sind auch aufeinanderfolgende Optimierungen wie
stringsbuilder → fmt.Fprintf
go fix verwendet einen 3-Wege-Merge-Algorithmus, um Änderungskonflikte automatisch zusammenzuführen
- Bei Syntaxkonflikten wird die betreffende Änderung übersprungen und eine Warnung ausgegeben
- Semantische Konflikte (z. B. entfernte Variablen oder ungenutzte Imports) erfordern manuelle Anpassungen
- Unnötige Imports werden automatisch entfernt
Integration in das Go-Analyse-Framework
go vet und go fix wurden so integriert, dass sie ein gemeinsames Analyse-Framework nutzen
vet konzentriert sich auf die Fehlererkennung, fix auf sichere automatische Korrekturen
- Analyzer können über verschiedene Treiber ausgeführt werden, darunter
unitchecker, multichecker, gopls, staticcheck und Tricorder
- Über das Fact-System ist ein Informationsaustausch zwischen Paketen möglich
- Beispiel: Es lässt sich ableiten, dass
log.Printf ein Wrapper von fmt.Printf ist
gopls bietet Echtzeitdiagnosen und Vorschläge für automatische Korrekturen
Verbesserungen an der Analyse-Infrastruktur
- Durch die Erweiterung des Pakets
inspector wurde die Effizienz der AST-Durchsuchung verbessert; der Typ Cursor unterstützt Navigation nach oben, unten, links und rechts
- Die Indizierung von Funktionsaufrufen über
typeindex erhöht die Analysegeschwindigkeit um bis zu das 1000-Fache
- Weitere Verbesserungen:
- Bereitstellung eines Abhängigkeitsgraphen der Standardbibliothek
- Unterstützung für Go-Versionsabfragen pro Datei
- Ausbau von Refactoring-Primitiven, um sichere Codeänderungen wie das Auskommentieren zu ermöglichen
- Einige Modernizer wurden wegen subtiler Verhaltensänderungen ausgeschlossen (Beispiel:
append([]string{}, slice...) → slices.Clone(slice))
- Geplant sind außerdem eine Pattern-Matching-Engine, ein automatisches Test-Harness und eine Bibliothek präziser Änderungsoperatoren
Das Self-service-Paradigma
- Ab Go 1.26 wird die Einführung eines Self-service-Analysemodells angekündigt
- Entwickler können Modernizer für ihre eigenen APIs definieren und verteilen
- Die Ausführung ist auf Projektebene ohne zentrales Freigabeverfahren möglich
- Als erster Schritt ist eine Annotation-driven inliner-Funktion als Vorschau enthalten
- Zukünftige Pläne:
- Ausführung benutzerdefinierter Analyzer per dynamischem Laden (innerhalb von
go fix oder gopls)
- Verallgemeinerung kontrollflussbasierter Checks, z. B. Prüfung von Invarianten wie „open vor close“ oder „lock vor unlock“
- Ziel ist eine höhere Wartungseffizienz und die schnellere Einführung neuer Go-Funktionen
1 Kommentare
Hacker-News-Kommentare
Als sich LLM-Code-Assistenten Ende 2024 rasant verbreiteten, war interessant zu sehen, dass solche Tools dazu neigen, den bestehenden Go-Code-Stil aus ihren Trainingsdaten unverändert nachzubilden
Selbst wenn man sie anwies, moderne Syntax zu verwenden, ignorierten sie das oft oder bestritten sogar, dass es sie überhaupt gibt
Damit künftige Modelle die neuesten Go-1.25-Idiome widerspiegeln, muss der gesamte Open-Source-Code auf diesen Stil aktualisiert werden
magic_quotesAber wenn einmal falsche Daten in ein LLM eingeflossen sind, ist eine Korrektur fast unmöglich
Es ist schwer nachzuverfolgen, auf welcher Grundlage das Modell zu seinen Schlussfolgerungen kommt, und man kann nur hoffen, dass es in der nächsten Modellgeneration behoben wird
Er wirkt simpel und kommt durch Reviews, in Wirklichkeit fehlen aber Fehlerbehandlung und Edge Cases
Gibt man den Code nach dem Review erneut an ein LLM, bekommt man scheinbar korrigierten Code zurück, in dem dann jedoch Data Races oder Deadlocks entstehen
Das ist ein Problem, das sich bei fast allen Modellen wiederholt
Go ist dank seiner Abwärtskompatibilität so stabil, dass der Code zwar kompiliert, sich der Stil aber stark unterscheidet
Bei Python führen API-Änderungen zu echten Kompatibilitätsbrüchen
Trotzdem ist Go wegen seiner Sprachstabilität und Standardbibliothek als Sprache für Codegenerierung hervorragend
Wie Rob Pike gewarnt hat, ist diese Technik eine Verschmutzung des Software-Ökosystems
Viele Menschen wollen den Slop der „Bequemlichkeit“, aber genau das ist der Kern des Problems
Ein Tool, das Quellcode automatisch in den neuesten Stil umwandelt, ist wirklich großartig
OpenRewrite für Java ist ein bekanntes Beispiel, aber für andere Sprachen fällt mir kaum etwas Vergleichbares ein
Wenn so etwas wie bei Go direkt in die Sprache eingebaut ist, erhöht das die Sprachreife enorm
Ich vermute, dass neue Sprachen künftig diesen integrierten Ansatz von Go als Vorbild nehmen werden
JetBrains-IDEs können Millionen Zeilen Code auf einmal refaktorisieren oder automatisch in neue Syntax umwandeln
Es gibt auch Funktionen wie ConvertToPrimaryConstructor
Außerdem arbeitet Structural Search and Replace nicht auf bloßer Textebene, sondern auf Ebene der Sprachsyntax
Die Roslyn-Analyzer von .NET bieten in der IDE ebenfalls Vorschläge zur Codekorrektur
Tutorial-Link
Dadurch ist der Code deutlich sauberer geworden
Es ersetzt etwa
concatundmapdurchconcatMapoder vereinfacht unnötigeif-AusdrückeLSP-Server sind funktional schwach und unterstützen nicht einmal grundlegende Refactorings wie das Entfernen von Argumenten
Ich überlege, ob sich das mit jscodeshift oder in Kombination mit Claude umsetzen ließe
Dank solcher Auto-Fix-Tools (
go fix) ist Go wirklich eine hervorragende SpracheIch freue mich darauf, dass auch das neue Feature
rangeintkünftig automatisch übergo fixübernommen wirdGroßes Lob an das Go-Team
Auch die Kompiliergeschwindigkeit ist kaum zu glauben
for-Schleifen selbst mit regulären Ausdrücken gesucht und geändert, heute erledigt dieses Tool das auf viel elegantere WeiseIm Artikel wurde es nicht erwähnt, aber meine Lieblingsfunktion ist die Direktive
//go:fix inlineSie fügt einzeilige Funktionen beim Aufrufer inline ein
Damit können Bibliotheksautoren alte Funktionen ganz natürlich automatisch auf neue Versionen migrieren
Selbst wenn sich die SemVer ändert, ist mit
go fixein automatisches Upgrade möglichIn einem kürzlich gesehenen Wes-McKinney-Podcast hieß es, dass Go wegen seines schnellen Compile-Run-Zyklus, des starken Typsystems und der Multithreading-Sicherheit ideal für Coding Agents sei
Das hat mein Interesse an Go wieder geweckt
Das etablierte Tooling und die Konventionen von Go helfen enorm bei agentenbasierter Entwicklung
Mit
go run main.golässt sich die Entwicklungsumgebung sofort starten, dazu kommen mehrere Worktrees, zentrale Konfiguration und sogar migrierte DatenbankenSolche Tools werden in housecat-inc/cheetah geteilt
Ich denke darüber nach,
go fixin den schnellen Zyklus ausgo generate,go build,go testundgo vetaufzunehmenWährend ich Python lerne, fällt mir auf, dass es zu viele und uneinheitliche Wege gibt, dieselbe Aufgabe zu lösen
Fast vermisse ich schon C, wo es nur einen Weg gibt
Ich frage mich, ob Go diesen Punkt erreicht hat
Ich möchte wissen, ob es eine Sprache ist, in der man auch ohne Hilfe von LLMs Best Practices befolgen kann
Beeindruckend ist, wie konsequent sie unnötige Komplexität vermeidet und Einfachheit bewahrt
Ich würde sie jedem empfehlen, der von der Unübersichtlichkeit von Python müde geworden ist
Das Konzept eines Self-Service-Analyzers ist wirklich spannend
Ich kann mir gut vorstellen, dass große Bibliotheks- oder Infrastrukturteams es aktiv einsetzen werden
Mit solchen Tools fragt man sich fast, ob nicht auch Sprachen ohne Abwärtskompatibilität praktikabel wären
In der TypeScript-Welt übernimmt biome eine ähnliche Rolle
Es empfiehlt zum Beispiel
forEachdurchfor...ofzu ersetzen, und zusammen mit ultracite wird der Workflow deutlich reibungsloserIn der Datei
agents.mdhabe ich festgehalten: „Nach Änderungenbiome fixausführen“; dadurch bleibt die Codequalität automatisch erhaltenIm Vergleich zu eslint ist das eine viel leichtere und effizientere Erfahrung