- Diese Release verbessert rund um generische Methoden Struct-Literale und Typherleitung und ergänzt zugleich praktische Funktionen in Standardbibliothek, Runtime und Toolchain
- Durch größenspezialisierte Speicherallokation sinken die Kosten mancher Allokationen unter 80 Byte um bis zu 30 %; bei allokationsintensiven Programmen sind etwa 1 % Leistungsplus und ein Binärgrößenzuwachs von rund 60 KB zu erwarten
encoding/json/v2ist offiziell verfügbar, das bisherigeencoding/jsonnutzt intern ebenfalls v2, und ein Standard-UUID-Paket sowie ML-DSA-Signaturen auf Basis von FIPS 204 kommen hinzu- Mit dem
goroutineleak-Profil, pprof-Labels in Tracebacks,synctest.Sleepfür virtuelle Zeit und einem In-Memory-HTTP-Testserver werden Diagnose und Concurrency-Tests einfacher - Ungepufferte Timer-Kanäle, automatisches Leeren von HTTP-Response-Bodys und strengere Beschränkungen für
//go:linknamekönnen bestehenden Code beeinflussen, daher ist vor dem Umstieg auf Go 1.27 eine Kompatibilitätsprüfung nötig
Sprache und Typsystem
- Das Kernstück von Go 1.27, generische Methoden, kann eigene Typparameter deklarieren, die vom Receiver unabhängig sind
- Zuvor konnten nur Top-Level-Funktionen generisch sein, sodass selbst typgebundene Operationen als Paketfunktionen geschrieben werden mussten
- Operationen wie
Box[T].Map[U], die einen anderen Elementtyp als den Eingabetyp zurückgeben, lassen sich nun als Methoden definieren - Interfaces können weiterhin keine Typparameter-Methoden deklarieren, und generische Methoden können auch kein Interface implementieren
- Für Schlüssel in Struct-Literalen sind nun nicht nur Feldnamen der obersten Ebene, sondern auch gültige Feldselektoren erlaubt
- Promotete Felder aus eingebetteten Structs lassen sich direkt initialisieren, etwa mit
User{ID: 7}
- Promotete Felder aus eingebetteten Structs lassen sich direkt initialisieren, etwa mit
- Die Typherleitung für Funktionen wird auf Konvertierungen und zusammengesetzte Literale ausgeweitet
- Bei
[]func([]int) int{first, last}werden die Typargumente generischer Funktionen aus dem erwarteten Funktionstyp hergeleitet - Zuvor war eine explizite Instanziierung wie
first[int],last[int]nötig
- Bei
Runtime und Performance
- Der Compiler ruft größenspezialisierte Allokationsroutinen auf und senkt damit die Kosten mancher Speicherallokationen unter 80 Byte um bis zu 30 %
- Für reale allokationsintensive Programme wird ein Gesamt-Performancegewinn von etwa 1 % erwartet
- Codeänderungen sind nicht nötig, aber die Binärdatei wächst unabhängig von der Workload um etwa 60 KB
- Deaktivieren lässt sich das mit
GOEXPERIMENT=nosizespecializedmalloc, diese Option soll aber in Go 1.28 entfernt werden
- Drei standardmäßig aktivierte Compiler-Optimierungen kommen hinzu
- ein Known-Bits-Dataflow-Pass, der Bits verfolgt, die sicher 0 oder 1 sind, und redundante Operationen entfernt
- Loop-Invariant-Code-Motion, die während einer Schleife unveränderte Berechnungen aus der Schleife herauszieht
- Kompilierung passender
switch-Anweisungen inklusivefallthroughzu Nachschlagetabellen
- Das experimentelle
GOEXPERIMENT=mapsplitgroupändert das Speicherlayout von Map-Gruppen vonKVKVKVKVzuKKKKVVVV; standardmäßig ist es deaktiviert - Der Linker verschiebt Typdeskriptoren und itabs in einen eigenen Abschnitt
.go.typeund entfernttypelinksunditablinksreflect.typelinksgibt dadurch Typen statt Offsets zurück, was Bibliotheken betreffen kann, die per//go:linknameauf dieses Symbol zugreifen
Goroutine-Diagnose und Profiling
- Module mit
go.modauf Go 1.27 oder neuer zeigen in den Goroutine-Headern von Tracebacks Labels ausruntime/pprofan- Mit
pprof.Doangehängte Kontexte wie{request: 42}erscheinen in Crash-Dumps, beiSIGQUITund in der Ausgabe vonruntime.Stack - Damit sensible Labels nicht in Tracebacks auftauchen, kann weiter
GODEBUG=tracebacklabels=0verwendet werden
- Mit
- Der in Go 1.26 experimentelle Goroutine-Leak-Detektor wird als offizielles
goroutineleak-Profil übernommen- Er führt GC aus, sucht Goroutinen, die etwa an Kanälen oder Mutexen dauerhaft nicht weiterlaufen können, und gibt ihre Stacks aus
- In Services lässt sich das über den Endpunkt
/debug/pprof/goroutineleaksammeln;GOEXPERIMENTist nicht mehr nötig
Kryptografie und Identifikatoren
- Das neue Paket crypto/mldsa implementiert mit ML-DSA die Post-Quanten-Signatur aus FIPS 204
- Die drei Parametersätze
MLDSA44,MLDSA65,MLDSA87balancieren Schlüssel- und Signaturgröße gegen das Sicherheitsniveau aus - ML-DSA wird auch zu Schlüsseln und Signaturen in
crypto/x509sowie zu TLS-1.3-Signaturverfahren incrypto/tlshinzugefügt
- Die drei Parametersätze
- Das neue Standardbibliotheks-Paket uuid erzeugt und parst RFC-9562-UUIDs mit kryptografisch sicheren Zufallswerten
uuid.New()wählt eine für allgemeine Zwecke geeignete Variante,NewV4()erzeugt reine Zufalls-UUIDs,NewV7()zeitlich geordnete UUIDs nach Erstellungszeit- Zufallsbasierte UUIDs sind vergleichbar, sodass
==direkt verwendet werden kann - Nach Zeit sortierbare UUID v7 eignet sich gut als Datenbankschlüssel
JSON- und Datenverarbeitungs-APIs
- encoding/json/v2 und das Low-Level-
encoding/json/jsontextsind ohneGOEXPERIMENT=jsonv2verfügbar- Auch das bisherige
encoding/jsonv1 nutzt intern die v2-Implementierung - Abgesehen von einzelnen Fehlermeldungstexten bleibt das bisherige Verhalten erhalten, eine Migration ist also nicht nötig
- Bei Kompatibilitätsproblemen lässt sich mit
GOEXPERIMENT=nojsonv2die ursprüngliche v1-Implementierung wiederherstellen - Für Performance sortiert v2 Map-Schlüssel standardmäßig nicht, daher sollte in Tests mit stabilem Ausgabeformat
json.Deterministicgesetzt werden
- Auch das bisherige
strings.CutLastundbytes.CutLastteilen Werte am letzten Trennzeichen- Fehlt ein Trennzeichen, geben sie die gesamte Eingabe, einen leeren Nachteil und
falsezurück
- Fehlt ein Trennzeichen, geben sie die gesamte Eingabe, einen leeren Nachteil und
- Das generische
Hasher[T]inhash/maphashdefiniert Hash- und Gleichheitsstrategie gemeinsam- Gleiche Werte müssen zwingend denselben Hash haben
- Für vergleichbare Typen gibt es
ComparableHasher[T], ebenso sind benutzerdefinierte Strategien wie case-insensitive Strings möglich
math/big.Int.Divideberechnet Quotient und Rest gemeinsam und wendet explizit einen Rundungsmodus ausTrunc,Floor,Round,Ceilan- Je nach Rundungsmodus ändert sich auch der Rest; das ergänzt in Finanz- und Numerik-Code die Grenzen des bisherigen Abschneidens Richtung 0 mit
QuoundMod
- Je nach Rundungsmodus ändert sich auch der Rest; das ergänzt in Finanz- und Numerik-Code die Grenzen des bisherigen Abschneidens Richtung 0 mit
math/rand/v2.(*Rand).Nerzeugt mit einer eigenen*Rand-Quelle bereichsbegrenzte Zufallswerte für beliebige Integer- oder Duration-Typen
Portables SIMD
- Das experimentelle Paket simd bietet eine SIMD-API unabhängig von der Vektorgröße und wird mit
GOEXPERIMENT=simdaktiviert- Auf unterstützten Plattformen wird zu echten Hardware-Vektorinstruktionen kompiliert, sonst auf reine Go-Emulation zurückgegriffen
- Die Anzahl der Lanes von Typen wie
Float32sist nicht fest vorgegeben, sondern folgt der Hardwarebreite des jeweiligen Systems
- Die Standardbibliothek nutzt intern bereits
simd/archsimd-IntrinsicsMemHash32,MemHash64undStrHashder Swiss-Table-Maps wurden auf die neue SIMD-Basis umgestellt
Deterministische Tests
testing/synctest.Sleepführt virtuelle Zeit fort und wartet in einem Schritt, bis alle Goroutinen stabil sind- Innerhalb einer
synctest-Bubble vergeht keine reale Zeit, daher ist selbst eine Wartezeit von 2 Sekunden sofort abgeschlossen - Das ersetzt wiederholten Boilerplate-Code aus
time.Sleepundsynctest.Wait
- Innerhalb einer
httptest.NewTestServerstartet Server über ein virtuelles In-Memory-Netzwerk statt über echte TCP-Portssrv.Client()verbindet sich über einen prozessinternen Pipe direkt mit dem Handler- Durch automatische Bereinigung via
t.Cleanupistdefer srv.Close()nicht nötig - In Kombination mit
testing/synctestlassen sich auch HTTP-Roundtrips schnell und deterministisch in virtueller Zeit testen
Netzwerk- und Kompatibilitätsänderungen
- Kanäle, die von
time.After,time.NewTimer,time.NewTickerusw. zurückgegeben werden, sind nun immer synchrone ungepufferte Kanäle- Die frühere GODEBUG-Einstellung
asynctimerchan, die das alte Pufferverhalten zurückholte, wurde entfernt
- Die frühere GODEBUG-Einstellung
- Bei HTTP/1 liest
http.Response.Body.Closeungelesene Bodys bis zu einer konservativen Grenze weiter, um die Wiederverwendung von Verbindungen zu unterstützen- Wer sich bisher zum vorzeitigen Abbruch großer Downloads auf
Closeverlassen hat, muss mitTransport.DisableKeepAlivesdie Wiederverwendung deaktivieren
- Wer sich bisher zum vorzeitigen Abbruch großer Downloads auf
- HTTP/2-Server verstehen Client-Prioritäten nach RFC 9218 und bearbeiten Streams mit hoher Priorität zuerst
- Mit
Server.DisableClientPriority = truelässt sich das bisherige Round-Robin-Verhalten wiederherstellen
- Mit
crypto/x509.SystemCertPoolauf Windows und macOS unterstütztSSL_CERT_FILEundSSL_CERT_DIR- Sind diese Variablen gesetzt, werden Root-Zertifikate von der Platte gelesen und statt der Plattform-API der Go-Validator verwendet
- Deaktivieren lässt sich das mit
GODEBUG=x509sslcertoverrideplatform=0
- Die HTTP/2-Implementierung, die bisher in der 12.226 Zeilen langen generierten Datei
h2_bundle.gosteckte, wurde durch das echte Paketnet/http/internal/http2ersetzt - Zu
net/httpkommen HTTP/3-Hooks als Vorstufe vor externer Freigabe hinzu, und Teile der Testsuite laufen bereits unter HTTP/3- Eine öffentlich aufrufbare API gibt es noch nicht, aber die Basis für einen künftigen QUIC-basierten
http.Transportist enthalten
- Eine öffentlich aufrufbare API gibt es noch nicht, aber die Basis für einen künftigen QUIC-basierten
Toolchain
go testführt standardmäßig diestdversion-Vet-Prüfung aus, die die Nutzung von Standardbibliotheks-Symbolen erkennt, die neuer sind als die ingo.moddeklarierte Go-Version- Mit
go doc pkg@versionlässt sich die Dokumentation einer bestimmten Modulversion abrufen go doc -exlistet ausführbare Beispiele auf; wird ein Beispielname direkt angegeben, wird dessen Quelltext ausgegebengo fixerhält die Modernisierungs-Analyzeratomictypes,embedlit,slicesbackward,unsafefuncswaitgroupwird inwaitgroupgoumbenannt,fmtappendfentfällt
- In Modulen ab Go 1.27 fasst
go mod tidyverstreuterequire-Blöcke zu zwei Blöcken für direkte und indirekte Abhängigkeiten zusammen und behält Kommentare bei go tool trace -http=:6060bindet bei alleiniger Portangabe nur an localhost; für externen Zugriff muss eine Adresse explizit angegeben werden- Der
go-Befehl entfernt die Unterstützung für das Versionsverwaltungssystem Bazaar (bzr) compile,link,asm,cgo,cover,packunterstützen Response-Dateien im GCC-Format (@file), um Beschränkungen der Kommandozeilenlänge zu umgehen
Unicode und Sicherheitsgrenzen
- Die Unicode-Daten der Standardbibliothek werden von Unicode 15 auf Unicode 17 aktualisiert
- Auch in Unicode 16 hinzugekommene Zeichen werden korrekt als Symbole bzw. druckbare Zeichen klassifiziert
- Ein Problem wurde behoben, bei dem sich mit
os.Root.ReadDirundReaddiraus dem Root-Verzeichnis ausbrechen ließ - Nicht autorisierte Nutzung von
//go:linknamewird weiter erschwert- Die Direktive
linknamestdmarkiert linknames, die nur die Standardbibliothek importieren darf - Der Linker prüft nun auch den Zugriff per linkname auf Assemblersymbole, daher sollten Programme mit Abhängigkeit von inoffiziellen internen Symbolen frühzeitig getestet werden
- Die Direktive
1 Kommentare
Lobste.rs-Kommentare
Könnte die beste Release aller Zeiten sein. SIMD, uuid, jsonv2 sind endlich dabei
Etwas am Thema vorbei, aber ein gutes Beispiel dafür, wie Bugs entstehen, wenn man alles als String behandelt und die Verträge und Zusammenhänge zwischen Interface-Methoden nicht berücksichtigt
Equalignoriert die Groß-/Kleinschreibung, aberHashverwendet den in Kleinbuchstaben umgewandelten Wert. Allerdings definierenEqualFoldundToLowernicht dieselbe Äquivalenzrelationhttps://github.com/golang/go/issues/52204
"\u017F"(ſ, langes s) und"s"sind unterEqualFoldgleich, aber ihre jeweiligenToLower-Ergebnisse unterscheiden sich. Wenn man also"s"einfügt und danach"ſ", wird es wegen des unterschiedlichen Hashes als separater Eintrag eingefügtNoch lustiger ist, dass die Dokumentation genau vor diesem Fall warnt
https://github.com/golang/go/…
https://github.com/golang/go/…
Schön zu sehen, dass jemand dort weitermacht, wo Anton aufgehört hat
Ich mag Go, aber wenn in jeder Release weiter solche Features dazukommen, frage ich mich, ob die Go-Syntax wirklich elegant genug ist
func (b Box[T]) Map[U any](f func(T) U) Box[U] {Andererseits hat die Ausführlichkeit von Go und Zig den Vorteil, dass man nicht woanders hinscrollen muss, um die Empfängerdefinition zu finden. An der Aufrufstelle, die man durchaus für wichtiger als die Definition halten kann, sieht es ohnehin fast überall gleich aus, und der Typ muss auch nicht explizit angegeben werden
Ich war eine Weile weg von Go, deshalb freue ich mich auf jsonv2. Wenn es aber zum Standard wird, frage ich mich, ob Go damit nicht das lange gepflegte Kompatibilitätsversprechen bricht
encoding/json/v2importiert werden und ist daher eine explizite Entscheidung. Das bestehendeencoding/jsonverwendet intern zwar v2, garantiert aber weiterhin das bisherige Verhalten, und jsonv2 bietet auch Flags, um die Sonderfälle von v1 nachzubilden, verletzt also das Kompatibilitätsversprechen nicht