Go Kompatibilität mit Toolchain, GODEBUG und GOTOOLCHAIN

Go Kompatibilität mit Toolchain, GODEBUG und GOTOOLCHAIN

In diesem Artikel geht es um die Go Toolchain und das Go Kompatibilitätsversprechen.

Was bisher geschah…

Neben den Fixes für die For-Schleifen enthält die Go Version 1.22 einige weitere interessante Anpassungen. Mit der enthaltenen ServerMux-Implementierung kann nun auch ein Pattern-Matching verwendet werden, das bisher nicht möglich war. Zu diesem Thema gibt es viele Artikel und auch die offizielle Dokumentation des http-Package enthält viele Details und Beispiele dazu.

Die gesamte Liste der Änderungen in Go 1.22 lassen sich in den Release-Notes nachlesen. Wer möchte kann es dort nachlesen…

Ich hatte mir die Release-Notes durchgelesen und soweit verstanden. Da wir in Projekten meist mit dem Gin Web Framework gearbeitet haben, hatte ich noch keine Berührung mit den neuen Funktionen des ServerMux.

Da allerdings jetzt eine Microservice-Schulung anstand und wir versuchen die Schulungsunterlagen immer auf dem aktuellen Stand zu halten, und natürlich auch die neuen Features zeigen wollen, war es an der Zeit das bisherige Beispiel zu aktualisieren und das Pattern-Matching aufzunehmen.

Neue Schulungsinhalte

Neue Schulungsinhalte

Umstellung auf URL Pattern Matching

Gesagt getan und ich habe das super einfache Einstiegsbeispiel angepasst. Die Registrierung des Handlers war schnell angepasst und ein GET vor die Pfadangabe gesetzt.

http.HandleFunc("GET /", handler)

Ab sofort sollen nur noch, laut Doku, GET und HEAD Anfragen beantwortet werden…. sollen… mmmhhh…

… warum geht das bei allen anderen…. und bei mir nicht….??? Es kam wie es kommen musste und das Feature funktionierte nicht!

Go Pattern Matching steuern

In der Dokumentation und in allen Artikeln, die ich gefunden habe, hatte niemand das Problem. Es wurde allerdings eine Option erwähnt, mit der, in einer neuen Go Version, das alte Verhalten konfigurieren werden kann. Und zwar mit der Umgebungsvariablen:

GODEBUG=httpmuxgo121=1

Ich probierte es andersherum und meine Anwendung tat plötzlich was sie sollte. Das Pattern Matching arbeitete wie erwartet.

GODEBUG=httpmuxgo121=0 go run cmd/main.go

ABER ICH HATTE DOCH GO 1.22! … Ok ok, da viel es mir wie Schuppen von den Augen: Meine go.mod Datei!

module golang.source-fellows.com/seminar/simple-http

go 1.18

Das Beispiel wurde zum letzten Mal auf Version 1.18 aktualisiert. Und genau hier liegt das Problem (soviel zum Thema die Schulungsbeispiele werden immer aktualisiert - na ja, hier hat sich ja tatsächlich erstmal nichts getan, also kein Anpassungsbedarf).

Eine Anpassung der go.mod Datei führte erstmals zum erwarteten Verhalten und die Anwendung verhielt sich so, wie in allen anderen Dokumentationen.

module golang.source-fellows.com/seminar/simple-http

go 1.22.0

Doch was ist im Hintergrund passiert?

Was macht die GODEBUG Umgebungsvariable?

In Go Version 1.21 wurde die Nutzung der Umgebungsvariable GODEBUG offiziell festgelegt. Mit den hinterlegten Werten soll das Standardverhalten von Änderungen festgelegt werden, die nach dem Kompatibilitätsversprechen keine breaking-change darstellen, aber bestehende Anwendungen trotzdem brechen können.

Beispielsweise könnte eine Anwendung um einen Bug in der Go Standardbibliothek herum gebaut sein und nach dem Fix des Bugs läuft die Anwendung nicht mehr korrekt. Mit der Umgebungsvariablen soll also gesteuert werden ob sich die Go Bibliothek so verhalten soll wie sie es bisher auch getan hat.

Im Hinterkopf hatte man hier sicher die oben angesprochene Änderung der For-Loop.

Das Pattern-Matching aus meinem Beispiel ist ein solcher Fall. In der Standardbibliothek wurde ein neues Feature aufgenommen, das potenziell bestehende Anwendungen beeinträchtigen kann. Aus diesem Grund wurde der oben genannte Wert httpmuxgo121 eingeführt, mit dem das Standardverhalten des ServerMux konfiguriert werden kann.

Ist der Wert gesetzt (httpmuxgo121=1), wird das alte (bis Version Go 1.21) Verhalten eingesetzt, wenn nicht, wird das Verhalten von Go ab Version 1.22 verwendet. Das hatte ich durch das Setzen der Umgebungsvariable bestätigt.

Eine Liste sämtlicher GODEBUG Werte in den verschiedenen Go Versionen findet man auf der Go Webseite. Das sind einige. Zum Beispiel:

Welche Auswirkung hat Versionseintrag in der go.mod?

Jetzt aber zu der Frage was das alles mit der go.mod zu tun hat.

Ab Go Version 1.21 entscheidet sich die Go Runtime bzw. das Tooling welche GODEBUG Kompatibilitätseinstellungen standardmäßig verwendet werden sollen und nutzt hierzu die Information aus der go.work bzw. go.mod Datei.

Für jede Go Version gibt es im Hintergrund eine Liste der zugeordneten Kompatibilitätseinstellungen. Im Beispiel in etwa so (nicht alle Versionen sind aufgeführt):

  • Go Version 1.19 - httpmuxgo121=1
  • Go Version 1.20.1 - httpmuxgo121=1
  • Go Version 1.21.6 - httpmuxgo121=1
  • Go Version 1.22.0 - httpmuxgo121=0

Das heißt, steht in der go.mod eine Versionsangabe, wie in meinem Beispiel die Version 1.18, wird die Kompatibilität auf diese Version eingestellt und die GODEBUG Werte entsprechend gesetzt. Die Go Umgebung verhält sich so wie sie sich in der angegebenen Version verhalten hat bzw hätte.

Für mein Beispiel wurde dementsprechend, da in der go.mod die Version 1.18 angegeben war, das GODEBUG Flag für httpmuxgo121 automatisch auf 1 gesetzt. Neue Feature nicht aktiviert. Durch die Umstellung auf 1.22.0 wurde das Flag automatisch auf 0 gesetzt.

Kompatibilität rocks!

Wie mache ich ein Go-Update?

In meinem Fall hatte ich eine neuere Go-Version zur Verfügung. Wenn ich allerdings mit einer alten Go Version die Anwendnung nutzen möchte, tritt ein Kompatibilitätsproblem auf.

Wenn die go.mod Datei folgende Zeile enthält:

module golang.source-fellows.com/seminar/simple-http

go 1.22.0

und ich aktuell beispielweise die Go Version 1.21.7 installiert habe, dürfte der Compiler die Anwendung nicht kompilieren, da die go.mod eine neuere Go Versionsangabe enthält als tatsächlich installiert.

Der Compiler sollte seine Arbeit eintsellen und mich darauf hinweisen, dass hier wohl eine Inkompatibilität besteht. Das klappt allerdings. Die Anwendung wird kompiliert:

$ go run cmd/main.go

go: downloading go1.22.0 (linux/amd64)
go: updates to go.mod needed; to update it:
	go mod tidy
Go Toolchain - kein Stress

Go Toolchain - kein Stress

Go Toolchains - Ein Download!

In der obigen Ausgabe sieht man, dass eine neue Toolchain heruntergeladen wird. Das liegt an einem Feature der Go Version 1.21. In dieser Version wurden die Go Auslieferung unterteilt in:

  • Go Kommandozeilentootl / go command
  • enthaltene Toolchain

Standardmäßig wird beim Aufruf des go Kommandos in mitgelieferte Toolchain, bestehende aus Compiler, Assembler und anderen Tools, verwendet. Allerdings lässt sich mit der Umgebungsvariablen GOTOOLCHAIN oder mit einem Eintrag in der go.mod-Datei die zu verwendende Version einer Toolchain angeben.

Die Go-Umgebung lietet nun die Möglichkeit eine alternative Toolchain herunterzuladen und zu verwenden. Dieses Feature ist standardmäßig an und kann ebenfalls über die Umgebungsvariable GOTOOLCHAIN gesteuert werden. Mit dem Standardwert auto wird definiert, dass automatisch eine passende Toolchain heruntergeladen werden soll. Die Angabe einer konkreten Version führt zum entsprechendem Download.

go env -w GOTOOLCHAIN=go1.21.3

Toolchain im Beispiel

Innerhalb des Projektes meldet das go version Kommando dementsprechend (die go.mod Datei definiert hier die zu verwendende Toolchain):

$ go version
go version go1.22.0 linux/amd64

Im Pfad liegt immer noch die Version 1.21.7! Das heißt, in einem anderen Verzeichnis wird go version wieder 1.21.7 melden. Je nach Kontext bzw. Projekt, wird eine passende Go-Version verwendet.

Kompatibilität rocks!!

WOW! Ab Version 1.21 ist eigentlich fast kein “richtiges” Update der Go-Version nötig. Auch wenn es ein Kompatibilitätsversprechen in Go gibt, unterstützt die Go Umgebung nicht nur eine Source-Code Kompatibilität sondern auch eine Verhaltens-Kompatibilität. Ein echtes Feature!

04.03.2024

 

Der Author auf LinkedIn: Kristian Köhler und Mastodon: @kkoehler@mastodontech.de

Kennen Sie schon das Buch zum Thema?

Der praktische Soforteinstieg für Developer und Softwarearchitekten, die direkt mit Go produktiv werden wollen.

  • Von den Sprachgrundlagen bis zur Qualitätssicherung
  • Architekturstil verstehen und direkt anwenden
  • Idiomatic Go, gRPC, Go Cloud Development Kit
  • Cloud-native Anwendungen erstellen
Microservices mit Go Buch

zur Buchseite beim Rheinwerk Verlag Rheinwerk Computing, ISBN 978-3-8362-7559-0 (als PDF, EPUB, MOBI und Papier)

Kontakt

Source Fellows GmbH

Source Fellows GmbH Logo

Lerchenstraße 31

72762 Reutlingen

Telefon: (0049) 07121 6969 802

E-Mail: info@source-fellows.com