- In Go 1.24 wurden die Funktionen rund um WebAssembly (Wasm) erweitert
- Die Direktive
go:wasmexportwurde hinzugefügt, sodass Go-Funktionen von außerhalb des Wasm-Moduls aufgerufen werden können - Außerdem wird ein „reactor“-Build-Modus für WASI unterstützt, mit dem Code langfristig aktiv ausgeführt werden kann
- Dadurch eröffnen sich neue Möglichkeiten, Go-Anwendungen in Wasm-Umgebungen flexibler zu erweitern
WebAssembly and the WebAssembly System Interface
- WebAssembly ist ein binäres Format, das entwickelt wurde, um performanten Low-Level-Code in Webbrowsern auszuführen
- Inzwischen wird es auch außerhalb des Browsers breit eingesetzt und kann über das WebAssembly System Interface (WASI) mit Systemressourcen interagieren
- Go begann mit Version 1.11 über den js/wasm-Port die Kompilierung nach Wasm zu unterstützen; in Version 1.21 kam mit dem neuen Port
GOOS=wasip1ein weiteres Ziel hinzu, das die System-Call-API von WASI Preview 1 adressiert
Wasm-Export von Go-Funktionen mit go:wasmexport
- Mit der in Go 1.24 neu hinzugefügten Direktive
go:wasmexportkönnen Go-Funktionen als Export bereitgestellt werden, damit sie von außerhalb des Wasm-Moduls aufgerufen werden können - Beispiel: Wird eine Funktion mit
//go:wasmexport adddeklariert, kann der Wasm-Host diese Funktion aufrufen - Das ähnelt der
export-Direktive von cgo, ist aber mit einem einfacheren Mechanismus umgesetzt
Building a WASI Reactor
- Ein WASI-„reactor“ ist ein WebAssembly-Modul, das dauerhaft aktiv bleibt und auf Ereignisse oder Anfragen reagieren kann
- In Go 1.24 wird der Build eines WASI-Reaktors mit der Option
-buildmode=c-sharedunterstützt - Dieses Build-Flag weist den Linker an, keine
_start-Funktion (den Einstiegspunkt eines Kommandomoduls) zu erzeugen, sondern stattdessen eine_initialize-Funktion- Die Initialisierung des Reaktors erfolgt über die Funktion
_initialize, die vor dermain-Funktion aufgerufen werden muss
- Die Initialisierung des Reaktors erfolgt über die Funktion
- Zusammen mit einer Runtime wie Wazero lassen sich nach dem Aufruf von
_initializeexportierte Funktionen beliebig oft erneut aufrufen - Dieser Ansatz ist nützlich in Umgebungen, in denen Wasm als Plugin- oder Erweiterungsmechanismus für Anwendungen verwendet wird
Umfangreichere Typunterstützung zwischen Host und Client
- In Go 1.24 wurden die Einschränkungen für Parameter- und Rückgabetypen von Funktionen gelockert, die über
go:wasmimportaufgerufen werden - So können beispielsweise bool, string,
int32-Pointer oder Struct-Pointer übergeben werden- Aufgrund von Unterschieden zwischen 64-Bit- und 32-Bit-Umgebungen bestehen jedoch weiterhin Einschränkungen
- Dadurch lassen sich Go-Wasm-Anwendungen natürlicher und komfortabler schreiben, während unnötige Typkonvertierungen entfallen
Einschränkungen
- Wasm ist eine Single-Thread-Architektur ohne Parallelverarbeitung
go:wasmexport-Funktionen können neue Goroutinen erzeugen, aber Funktionen, die Hintergrund-Goroutinen starten, laufen nach der Rückkehr dergo:wasmexport-Funktion erst weiter, wenn das Go-basierte Wasm-Modul erneut aufgerufen wird- Einige Typbeschränkungen wurden zwar gelockert, dennoch gibt es weiterhin Einschränkungen bei den Typen, die mit
go:wasmimport- undgo:wasmexport-Funktionen verwendet werden können- Insbesondere bei der Übergabe zusammengesetzter Typen mit Pointern bestehen noch Beschränkungen
Fazit
- Der WASI-Reactor-Build und die Ergänzung von
go:wasmexportin Go 1.24 sind bedeutende Verbesserungen, die das Wasm-Ökosystem von Go stark erweitern - Dadurch können Entwickler vielfältigere Go-basierte Wasm-Anwendungen erstellen und neue Möglichkeiten für Go im Wasm-Ökosystem erschließen
3 Kommentare
Bevor Wasm/gc breit eingeführt wird, scheint es besser zu sein, für Wasm-Ziele mit einer Sprache ohne GC zu entwickeln.
In den Release Notes zu Go 1.24 wird das nur kurz erwähnt, aber das ist ein deutlich wichtigeres Update.
Hacker-News-Kommentare
Ein großes Problem ist, dass mit Go erzeugte WASM-Binärdateien sehr groß sind. TinyGo umgeht das, aber die Kompilierung ist langsam und bei der Auswahl der Bibliotheken ist Vorsicht geboten. Um beides zu überwinden, braucht man viel Geduld.
Das ist bemerkenswert. Man sollte sich merken:
Ich erinnere mich nicht mehr genau, ob es schon vor Go 1.24 möglich war, Go-Funktionen nach JS zu exportieren. Ich meine, ich konnte zuvor problemlos aus JS exportierte Go-Funktionen aufrufen.
goos=wasip1erzeugtes WASM-Modul zu übergeben, weiterhin gültig ist.Es wäre wohl „Go-artiger“ gewesen, alle Funktionen im Main-Paket zu exportieren, die mit einem Großbuchstaben beginnen. Da Exporte in der Sprache normalerweise so funktionieren, wäre es gut, Compiler-Direktiven nur dann zu verwenden, wenn man Funktionen, die mit einem Kleinbuchstaben beginnen, ausdrücklich benennen will.
cgo. Man folgt den bisherigen Beispielen. Die Benutzbarkeit liegt weiterhin außerhalb der Sprache.Es gibt keine Erwähnung der Arbeit mit dem WASM Component Model.
Ich frage mich, wie die Garbage Collection von Go und WASM funktioniert.
Ich wünschte, es gäbe eine Low-Level-Sprache mit starker Typisierung und hervorragender WASM-Unterstützung.
Ich frage mich, wie man ein laufendes WASM-Modul im Host-Programm debuggt.
Ich mache mir Sorgen, dass der Wunsch nach mehr WASM-Funktionen das junge Ökosystem irreversibel schädigen könnte. Die meisten Funktionen, die Go zu WASM hinzugefügt hat, könnten nativ umgesetzt werden, wenn der Vorschlag für das Component Model bereits gemergt worden wäre.