
lintpack ist ein Dienstprogramm zum Erstellen von Linter (statischen Analysatoren), die mit der bereitgestellten API geschrieben werden. Darauf aufbauend wird der einigen bekannte statische Analysator für Kritiker jetzt neu geschrieben.
Heute werden wir genauer lintpack
was lintpack
aus Sicht des Benutzers ist.
Am Anfang war Go-Kritiker ...
go-kritiker begann als Pilotprojekt, das eine Sandbox für das Prototyping fast aller statischen Analyseideen für Go war.
Eine angenehme Überraschung war, dass einige Leute Implementierungen von Detektoren für verschiedene Probleme im Code schickten. Alles war unter Kontrolle, bis sich eine technische Verschuldung ansammelte, die praktisch niemand beseitigen konnte. Die Leute kamen herein, fügten eine Bestätigung hinzu und verschwanden dann. Wer muss dann Fehler korrigieren und die Implementierung ändern?
Ein wichtiges Ereignis war der Vorschlag, Überprüfungen hinzuzufügen, die eine zusätzliche Konfiguration erfordern, dh solche, die von lokalen Vorkehrungen für das Projekt abhängen. Ein Beispiel ist das Aufdecken eines Copyright-Headers in einer Datei (Lizenz-Header) mithilfe einer speziellen Vorlage oder das Verbot des Imports einiger Pakete mit dem Vorschlag einer bestimmten Alternative.
Eine weitere Schwierigkeit war die Erweiterbarkeit. Es ist nicht für jeden bequem, seinen Code an das Repository eines anderen zu senden. Einige wollten ihre Prüfungen dynamisch verbinden, damit sie die go-critic
Quellcodes nicht ändern mussten.
Zusammenfassend sind hier die Probleme, die der Entwicklung von go-critic
im Wege standen:
- Eine Menge Komplexität. Zu viel Unterstützung, das Vorhandensein eines inhaberlosen Codes.
- Niedrige durchschnittliche Qualität.
experimental
bedeutete "fast einsatzbereit" und "besser gar nicht laufen". - Manchmal ist es schwierig zu entscheiden, ob die Überprüfung in den
go-critic
, und ihre Ablehnung widerspricht der ursprünglichen Designphilosophie. - Verschiedene Leute sahen
go-critic
unterschiedlich. Die meisten wollten es als CI-Linter haben, der mit gometalinter
.
Um die Anzahl der Diskrepanzen und inkonsistenten Interpretationen des Projekts irgendwie zu begrenzen, wurde ein Manifest geschrieben.
Wenn Sie zusätzlichen historischen Kontext und noch mehr Gedanken über die Kategorisierung statischer Analysatoren wünschen , können Sie sich die GoCritic- Aufzeichnung anhören , einen neuen statischen Analysator für Go . Zu diesem Zeitpunkt gab es noch kein Lintpack, aber einige der Ideen wurden an diesem Tag nach dem Bericht geboren.
Aber was wäre, wenn wir nicht alle Schecks in einem Repository speichern müssten?

go-critic
besteht aus zwei Hauptkomponenten:
- Durchführung der Prüfungen selbst.
- Ein Programm, das Go-validierte Pakete herunterlädt und Validierungen auf ihnen ausführt.
Unser Ziel: Schecks für den Linter in verschiedenen Repositories speichern und bei Bedarf zusammen sammeln zu können.
lintpack macht genau das. Es definiert Funktionen, mit denen Sie Ihre Prüfungen so beschreiben können, dass Sie sie dann durch den generierten Linter ausführen können.
Pakete, die mit lintpack
als Framework implementiert werden, werden als lintpack
kompatible oder lintpack
kompatible Pakete bezeichnet.
Wenn go-critic
lintpack
go-critic
auf Basis von lintpack
, konnten alle Checks in mehrere Repositories unterteilt werden. Eine der Optionen für die Trennung kann die folgende sein:
- Der Hauptsatz, in den alle stabilen und unterstützten Prüfungen gelangen.
- Contrib-Repository, in dem der Code liegt, der entweder zu experimentell ist oder keinen Betreuer hat.
- Anpassbare Prüfungen für ein bestimmtes Projekt.
Der erste Punkt ist von besonderer Bedeutung im Zusammenhang mit der Integration von Go-Kritiker in Golangci-Lint .
Wenn Sie auf der Ebene der go-critic
bleiben, hat sich für die Benutzer fast nichts geändert. lintpack
erstellt einen nahezu identischen Linter, während golangci-lint
alle verschiedenen Implementierungsdetails zusammenfasst.
Aber etwas hat sich geändert. Wenn neue lintpack
auf der Basis von lintpack
, haben Sie eine lintpack
Auswahl an vorgefertigten Diagnosen zur Erzeugung eines Linter. Stellen Sie sich für einen Moment vor, dass dies so ist und es weltweit mehr als 10 verschiedene Überprüfungssätze gibt.
Schnellstart

Um zu beginnen, müssen Sie lintpack
selbst installieren:
Erstellen Sie einen Linter mit dem lintpack
von lintpack
:
lintpack build -o mylinter github.com/go-lintpack/lintpack/checkers
Das Set enthält panicNil
, das panic(nil)
im Code findet und ihn durch etwas Unterscheidbares ersetzen panicNil
, da andernfalls recover()
nicht erkennen kann, ob panic
mit dem Argument nil
aufgerufen wurde oder überhaupt keine Panik aufgetreten ist.
Beispiel mit Panik (null)
Der folgende Code versucht, den Wert zu beschreiben, der aus recover()
:
r := recover() fmt.Printf("%T, %v\n", r, r)
Das Ergebnis ist für panic(nil)
und für ein Programm, das nicht in panic(nil)
, identisch.
Ein Beispiel für das beschriebene Verhalten .
Sie können den Linter in separaten Dateien mit Argumenten vom Typ ./...
oder Paketen (über deren Importpfad) starten.
./mylinter check bytes $GOROOT/src/bytes/buffer_test.go:276:3: panicNil: panic(nil) calls are discouraged
Standardmäßig reagiert diese Prüfung auch auf panic(interface{}(nil))
. Um dieses Verhalten zu überschreiben, setzen Sie skipNilEfaceLit
auf true
. Sie können dies über die Befehlszeile tun:
$mylinter check -@panicNil.skipNilEfaceLit=true ./panicNil/ ./panicNil/positive_tests.go:5:3: panicNil: panic(nil) calls are discouraged
Verwendung für cmd / lintpack und generierten Linter
Sowohl lintpack
als auch der generierte Linter verwenden das erste Argument, um einen Unterbefehl auszuwählen. Die Liste der verfügbaren Unterbefehle und Beispiele für deren Start erhalten Sie, indem Sie das Dienstprogramm ohne Argumente aufrufen.
lintpack not enough arguments, expected sub-command name Supported sub-commands: build - build linter from made of lintpack-compatible packages $ lintpack build -help $ lintpack build -o gocritic github.com/go-critic/checkers $ lintpack build -linter.version=v1.0.0 . version - print lintpack version $ lintpack version
Angenommen, wir haben den erstellten Linter mit dem Namen gocritic
:
./gocritic not enough arguments, expected sub-command name Supported sub-commands: check - run linter over specified targets $ linter check -help $ linter check -disableTags=none strings bytes $ linter check -enableTags=diagnostic ./... version - print linter version $ linter version doc - get installed checkers documentation $ linter doc -help $ linter doc $ linter doc checkerName
Das Flag -help
ist für einige Unterbefehle verfügbar, die zusätzliche Informationen enthalten (ich habe einige Zeilen zu breit ausgeschnitten):
./gocritic check -help
Dokumentation der installierten Prüfungen
Die Antwort auf die Frage "Wie erfahre ich etwas über den Parameter skipNilEfaceLit?" - Lesen Sie das schicke Handbuch (RTFM)!
Die gesamte Dokumentation zu installierten Prüfungen befindet sich in mylinter
. Diese Dokumentation ist über den Unterbefehl doc
verfügbar:
Wie bei der Unterstützung von Vorlagen in go list -f
können Sie eine Vorlagenzeile übergeben, die für das Ausgabeformat der Dokumentation verantwortlich ist. Dies kann beim Schreiben von Markdown-Dokumenten hilfreich sein.
Wo kann man nach Installationsprüfungen suchen?
Um die Suche nach nützlichen lintpack
zu vereinfachen, gibt es eine zentralisierte Liste von lintpack
kompatiblen Paketen: https://go-lintpack.imtqy.com/ .
Hier sind einige der Liste:
Diese Liste wird regelmäßig aktualisiert und kann angefordert werden. Jedes dieser Pakete kann verwendet werden, um einen Linter zu erstellen.
Der folgende Befehl erstellt einen Linter, der alle Überprüfungen aus der obigen Liste enthält:
lintpack build
umfasst alle Überprüfungen in der Kompilierungsphase. Der resultierende Linter kann in einer Umgebung platziert werden, in der es keine Quellcodes für die Implementierung der installierten Diagnose gibt. Bei statischer Verknüpfung ist alles wie gewohnt.
Dynamischer Paketanhang
Zusätzlich zur statischen Assembly können Plugins geladen werden, die zusätzliche Überprüfungen ermöglichen.
Die Besonderheit ist, dass die Checker-Implementierung nicht weiß, ob sie für die statische Kompilierung verwendet oder als Plug-In geladen wird. Es sind keine Änderungen am Code erforderlich.
Angenommen, wir möchten dem Linter panicNil
hinzufügen, können ihn jedoch nicht aus allen Quellen neu panicNil
, die bei der ersten Kompilierung verwendet wurden.
- Erstellen Sie
linterPlugin.go
:
package main
- Erstellen Sie eine dynamische Bibliothek:
go build -buildmode=plugin -o linterPlugin.so linterPlugin.go
- Führen Sie den Linter mit dem Parameter
-pluginPath
:
./linter check -pluginPath=linterPlugin.so bytes
Warnung: Die Unterstützung für dynamische Module wird über ein Plugin- Paket implementiert, das unter Windows nicht funktioniert.
Das Flag -verbose
kann Ihnen dabei helfen, herauszufinden, welche Prüfung -verbose
oder deaktiviert ist, und zeigt vor allem an, welcher Filter die Prüfung deaktiviert hat.
Beispiel mit -verbose
Beachten Sie, dass panicNil
in der Liste der enthaltenen Prüfungen angezeigt wird. Wenn wir das Argument -pluginPath entfernen, ist es nicht mehr wahr.
./linter check -verbose -pluginPath=./linterPlugin.so bytes debug: appendCombine: disabled by tags (-disableTags) debug: boolExprSimplify: disabled by tags (-disableTags) debug: builtinShadow: disabled by tags (-disableTags) debug: commentedOutCode: disabled by tags (-disableTags) debug: deprecatedComment: disabled by tags (-disableTags) debug: docStub: disabled by tags (-disableTags) debug: emptyFallthrough: disabled by tags (-disableTags) debug: hugeParam: disabled by tags (-disableTags) debug: importShadow: disabled by tags (-disableTags) debug: indexAlloc: disabled by tags (-disableTags) debug: methodExprCall: disabled by tags (-disableTags) debug: nilValReturn: disabled by tags (-disableTags) debug: paramTypeCombine: disabled by tags (-disableTags) debug: rangeExprCopy: disabled by tags (-disableTags) debug: rangeValCopy: disabled by tags (-disableTags) debug: sloppyReassign: disabled by tags (-disableTags) debug: typeUnparen: disabled by tags (-disableTags) debug: unlabelStmt: disabled by tags (-disableTags) debug: wrapperFunc: disabled by tags (-disableTags) debug: appendAssign is enabled debug: assignOp is enabled debug: captLocal is enabled debug: caseOrder is enabled debug: defaultCaseOrder is enabled debug: dupArg is enabled debug: dupBranchBody is enabled debug: dupCase is enabled debug: dupSubExpr is enabled debug: elseif is enabled debug: flagDeref is enabled debug: ifElseChain is enabled debug: panicNil is enabled debug: regexpMust is enabled debug: singleCaseSwitch is enabled debug: sloppyLen is enabled debug: switchTrue is enabled debug: typeSwitchVar is enabled debug: underef is enabled debug: unlambda is enabled debug: unslice is enabled
Um Verwirrung zu vermeiden, sollten die Hauptunterschiede zwischen den Projekten beschrieben werden.
gometalinter und golangci-lint integrieren in erster Linie andere, oft sehr unterschiedlich implementierte Linters und bieten einen bequemen Zugang zu ihnen. Sie richten sich an Endbenutzer, die statische Analysegeräte verwenden.
lintpack vereinfacht die Erstellung neuer Linters und bietet ein Framework, mit dem verschiedene auf seiner Basis implementierte Pakete in derselben ausführbaren Datei kompatibel sind. Diese Überprüfungen (für Golangci-Lint) oder die ausführbare Datei (für Gometalinter) können dann in die oben genannten Meta-Linters eingebettet werden.
Angenommen, eine der mit lintpack
kompatiblen Prüfungen ist Teil von golangci-lint
. Wenn es ein Problem im Zusammenhang mit der Benutzerfreundlichkeit gibt, liegt dies möglicherweise in der Verantwortung von golangci-lint
. Wenn es sich jedoch um einen Fehler bei der Implementierung der Verifizierung selbst handelt, ist dies das Problem der Autoren des Verifizierungs-Lintpack-Ökosystems.
Mit anderen Worten, diese Projekte lösen verschiedene Probleme.
Was ist mit Go-Kritiker?
Der Portierungsvorgang von go-critic
lintpack
nach lintpack
ist bereits abgeschlossen. Checkers finden Sie im Repository von go-critic
lintpack
/ Checkers .
Es macht wenig Sinn, go-critic
golangci-lint
außerhalb von golangci-lint
, aber mit lintpack
können Sie die Prüfungen installieren, die nicht im go-critic
lintpack
go-critic
. Dies können beispielsweise von Ihnen geschriebene Diagnosen sein.
Fortsetzung folgt
Im nächsten Artikel erfahren Sie, wie Sie Ihre eigenen lintpack
kompatiblen Prüfungen erstellen.
Dort analysieren wir, welche Vorteile Sie bei der Implementierung Ihres Lintpack-basierten lintpack
gegenüber der Implementierung von Grund auf erhalten.
Ich hoffe, Sie haben Appetit auf neue Schecks für Go. Lassen Sie mich wissen, wie viel statische Analyse zu viel wird. Wir werden dieses Problem schnell gemeinsam lösen.