Go-Module sind klasse, aber es gibt ein kleines Problem
Die meisten Programmiersprachen und Tools unterstützen das Konzept der Pakete und meistens gibt es Versionen dieser Pakete. Das Tolle an Versionen, egal ob sie von Tools verwendet werden oder nicht, ist, dass die Entwickler klar kommunizieren können, welche Abhängigkeiten bestehen, um das Endprodukt zu erstellen.
Go hat sich seit seinen Anfängen mit der Versionierung ziemlich schwergetan und das führte dazu, dass Entwickler begonnen haben, ihre eigenen Werkzeuge wie gb und glide zusammenzustellen. Anfang 2017 wurde vom Go-Team mit Dep das offizielle Experiment für die Paketverwaltung in Go gestartet. Die mit Dep und anderen Sprachen gesammelten Erfahrungen führten zum offiziellen Vorschlag für Go-Module, die in Go 1.11 eingeführt wurden.
Was ist also das Problem?
Verstehen Sie mich nicht falsch – ich bin begeistert von der Einführung der Go-Module, da sie eine Reihe von Problemen lösen. Es bringt uns auch weg vom hässlichen Konzept des Vendoring. Seien wir ehrlich, wer will schon eine Kopie der Quellen jeder Abhängigkeit in seinem Projekt aufbewahren, riskieren, Abhängigkeiten ganz zu verlieren (wir haben aus left-pad gelernt, stimmts?) oder seine Kollegen ein wenig mit neuen Versionen experimentieren lassen?
All dies sind Probleme, die Go Modules löst, und es führt sogar eine Umgebungsvariable namens GOPROXY ein, die es Entwicklern ermöglicht, alle Modul-Download-Anfragen über einen Proxy zu senden. Das an sich ist natürlich großartig für Unternehmen, die einen Cache von Versionen behalten wollen (und nicht jedes Mal die Abhängigkeit herunterladen wollen), die Sicherheit im Auge behalten wollen (und den Zugriff auf das Internet von ihren Build-Servern aus begrenzen wollen) unter vielen anderen Gründen. Allerdings gibt es ein kleines Problem. GOPROXY ist äußerst unpraktisch.
Das Problem mit GOPROXY
Derzeit ist die Verwendung von GOPROXY eine "Alles-oder-Nichts"-Übung. Das bedeutet, dass alle Abhängigkeiten in Ihrem gesamten Abhängigkeitsbaum (sowohl direkte als auch transitive) von diesem Proxy-Server aufgelöst werden müssen und der Go-Client fehlschlägt, wenn eine der Abhängigkeiten nicht in dieser Go-Registry vorliegen.
Mit anderen Worten: Wenn jemand eine neue App mit labstack/echo v3.3.5 und dgrijalva/jwt-go v3.2.0 in seiner go.mod-Datei erstellt und go install mit gesetzter GOPROXY-Variable ausführt, wird der go-Client fehlschlagen, wenn nicht beide Module, ihre angeforderten Versionen und alle ihre transitiven Abhängigkeiten auf diesem Proxy verfügbar sind. Wenn ich also nicht absolut sicher bin, dass mein gesamter Abhängigkeitsbaum vom Proxyserver aufgelöst werden kann, der intern oder extern sein kann, wird dieser Ansatz nicht funktionieren.
Fallbacks
Wie für jedes Problem muss es auch hier eine Lösung geben, oder? Richtig! Es ist sogar so, dass die Lösung bereits existiert. Ein Thread im Golang-Repository auf GitHub (von Aaron Schlesinger aus dem Athens-Team gestartet) umreißt das Problem und die Lösung, die Proxies darauf beschränkt, nur einige Module zu liefern. Erinnern wir uns an das vorherige Beispiel: Wenn eines der beiden Module auf dem Proxy verfügbar ist und eines nicht, wird der Build erfolgreich sein. Ein Modul wird vom Proxy heruntergeladen und das andere wird von einem Versionsverwaltungssystem heruntergeladen.
Die Option, einen solchen Fallback zu haben, würde einen Teil des Problems lösen. Einige Go-Modul-Proxys, wie Athens, sind in der Lage, leere go.mod-Dateien aus diesen nicht aufgelösten Anfragen zu konstruieren, was wiederum andere Probleme verursacht.
Vervollständigen der Lösung
Die ideale Lösung würde es dem Benutzer erlauben, seine GOPROXY zu spezifizieren, Fallbacks zu verwenden, falls das Modul nicht verfügbar ist, und, das ist das Wichtigste, diese Module auf den Proxy hochzuladen. Dieser Ansatz bedeutet, dass immer nur ein Entwickler eine Version eines Moduls herunterlädt und es danach im Proxy-Server für die Verwendung durch andere Entwickler und CI-Server zur Verfügung steht. Da nicht alle Unternehmen zulassen, dass sich ihre CI-Server mit dem Internet verbinden, würde dies das Problem wirklich lösen und Go-Module perfekt für Entwickler machen. Wenn Sie sich fragen, wie das aussehen könnte, dann werfen Sie einen Blick auf die JFrog CLI, die all diese Logik eingebaut hat. Ich denke, wir sind uns alle einig, dass dies eine Funktion ist, die wir von der Sprache selbst erwarten…