1 Punkte von GN⁺ 2025-02-16 | 3 Kommentare | Auf WhatsApp teilen
  • In Go 1.24 wurden die Funktionen rund um WebAssembly (Wasm) erweitert
  • Die Direktive go:wasmexport wurde 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=wasip1 ein 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:wasmexport kö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 add deklariert, 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-shared unterstü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 der main-Funktion aufgerufen werden muss
  • Zusammen mit einer Runtime wie Wazero lassen sich nach dem Aufruf von _initialize exportierte 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:wasmimport aufgerufen 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 der go: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- und go: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:wasmexport in 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

 
click 2025-02-16

Bevor Wasm/gc breit eingeführt wird, scheint es besser zu sein, für Wasm-Ziele mit einer Sprache ohne GC zu entwickeln.

 
xguru 2025-02-16

In den Release Notes zu Go 1.24 wird das nur kurz erwähnt, aber das ist ein deutlich wichtigeres Update.

 
GN⁺ 2025-02-16
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.

    • Um Go WASM auf Cloudflare Workers auszuprobieren, braucht man wegen der Binärgröße ein Abonnement.
    • Beim letzten Versuch ließ sich Hello-World ausführen, komplexere Dinge überschritten aber die Größenbegrenzung.
    • Eine bedauerliche Situation.
  • Das ist bemerkenswert. Man sollte sich merken:

    • Die WebAssembly-Arbeit in Go wurde nicht vom Go-Team, sondern von Freiwilligen entworfen und implementiert. Daher hängt der Zeitplan von der Verfügbarkeit der Freiwilligen ab.
  • 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.

    • Es wäre hilfreich, wenn erklärt würde, wie sich die neuen WASI-Funktionen im Vergleich zu vorher verbessert haben (abgesehen davon, dass über FFI mehr Typen unterstützt werden).
    • Zweite Frage: Man konnte Strings und komplexe Typen aus dem Instanzspeicher eines WASM-Moduls extrahieren, indem man Pointer zu Integern castet. Wenn garantiert ist, dass die binäre Darstellung meines Typs in Go stabil ist, frage ich mich, ob diese Methode, Pointer an ein mit goos=wasip1 erzeugtes 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.

    • Das ist dieselbe Exportmethode wie beim bestehenden 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.

    • Der Standard entwickelt sich langsam weiter, und mit zunehmender Verbreitung besteht das Risiko, dass nicht standardisierte Funktionen wie WASI auf Dauer unterstützt werden müssen.