Go 1.21 agrega un nuevo puerto dirigido a la API SYSCALL de Vista previa 1 de WASI a través de la nueva GOOS
valor wasip1
. Este puerto se basa en el puerto WebAsmbly existente introducido en GO 1.11.
¿Qué es WebAssembly?
Webassembly (WASM) es un formato de instrucción binaria originalmente diseñado para la internet. Representa un estándar que permite a los desarrolladores ejecutar un código de alto rendimiento y de bajo nivel directamente en navegadores internet a velocidades casi nativas.
GO primero agregó soporte para compilar a WASM en la versión 1.11, a través del js/wasm
puerto. Esto permitió el código GO compilado utilizando el compilador GO para ejecutarse en los navegadores internet, pero requirió un entorno de ejecución de JavaScript.
A medida que el uso de WASM ha crecido, también lo han hecho casos de uso fuera del navegador. Muchos proveedores de la nube ahora están ofreciendo servicios que permiten al usuario ejecutar ejecuciones de WASM directamente, aprovechando la nueva API SYSCALL de la interfaz del sistema WebAssembly (WASI).
La interfaz del sistema WebAssembly
WASI outline una API SYSCall para los ejecutables de WASM, lo que les permite interactuar con recursos del sistema, como el sistema de archivos, el reloj del sistema, las utilidades de datos aleatorios y más. El último lanzamiento de la especificación de WASI se llama wasi_snapshot_preview1
de la cual derivamos el GOOS
nombre wasip1
. Se están desarrollando nuevas versiones de la API, y apoyarlas en el compilador Go en el futuro probablemente significará agregar un nuevo GOOS
.
La creación de WASI ha permitido que una serie de tiempos de ejecución de WASM (anfitriones) estandarizaran su API SYSCALL a su alrededor. Los ejemplos de hosts Wasm/Wasi incluyen Wasmtime, Wazero, Wasmedge, Wasmer y NodeJs. También hay una serie de proveedores de la nube que ofrecen alojamiento de ejecutables WASM/WASI.
¿Cómo podemos usarlo con GO?
Asegúrese de haber instalado al menos la versión 1.21 de Go. Para esta demostración, usaremos el host Wasmtime para ejecutar nuestro binario. Comencemos con un easy major.go
:
package deal major
import "fmt"
func major() {
fmt.Println("Hiya world!")
}
Podemos construirlo para wasip1
Usando el comando:
$ GOOS=wasip1 GOARCH=wasm go construct -o major.wasm major.go
Esto producirá un archivo, major.wasm
que podemos ejecutar con wasmtime
:
$ wasmtime major.wasm
Hiya world!
¡Eso es todo lo que se necesita para comenzar con Wasm/Wasi! Puede esperar casi todas las características de Go para trabajar con wasip1
. Para obtener más información sobre los detalles de cómo funciona con Go, consulte la propuesta.
Ejecución de GO con wasip1
Go 1.24 movió los archivos de soporte WASM a
lib/wasm
. Para GO 1.21 – 1.23, use elmisc/wasm
directorio.
Construir y ejecutar un binario es fácil, pero a veces queremos poder ejecutar go take a look at
directamente sin tener que construir y ejecutar el binario manualmente. Related al js/wasm
Puerto, la distribución estándar de la biblioteca incluida en su instalación de GO viene con un archivo que lo hace muy fácil. Agregar el lib/wasm
directorio a tu PATH
Al ejecutar las pruebas GO y ejecutará las pruebas utilizando el host WASM de su elección. Esto funciona por go take a look at
Ejecutando automáticamente lib/wasm/go_wasip1_wasm_exec
Cuando encuentra este archivo en el PATH
.
$ export PATH=$PATH:$(go env GOROOT)/lib/wasm
$ GOOS=wasip1 GOARCH=wasm go take a look at ./...
Esto se ejecutará go take a look at
Usando Wasmtime. El host WASM utilizado se puede controlar utilizando la variable de entorno GOWASIRUNTIME
. Los valores compatibles actualmente para esta variable son wazero
, wasmedge
, wasmtime
y wasmer
. Este script está sujeto a cambios de ruptura entre las versiones GO. Tenga en cuenta que ir wasip1
Los binarios aún no se ejecutan perfectamente en todos los anfitriones (ver #59907 y #60097).
Esta funcionalidad también funciona cuando se usa go run
:
$ GOOS=wasip1 GOARCH=wasm go run ./major.go
Hiya world!
Envolviendo funciones de WASM en Go With Go: wasmimport
Además del nuevo wasip1/wasm
Puerto, GO 1.21 presenta una nueva directiva de compilador: go:wasmimport
. Instruye al compilador que traduzca las llamadas a la función anotada en una llamada a la función especificada por el nombre del módulo de host y el nombre de la función. Esta nueva funcionalidad del compilador es lo que nos permitió definir el wasip1
Syscall API en Go para admitir el nuevo puerto, pero no se limita a ser utilizado en la biblioteca estándar.
Por ejemplo, la API SYSCALL WASIP1 outline la random_get
función, y está expuesta a la biblioteca estándar GO a través de una envoltura de funciones definida en el paquete de tiempo de ejecución. Se parece a esto:
//go:wasmimport wasi_snapshot_preview1 random_get
//go:noescape
func random_get(buf unsafe.Pointer, bufLen dimension) errno
Este envoltorio de funciones se envuelve en una función más ergonómica para su uso en la biblioteca estándar:
func getRandomData(r []byte) {
if random_get(unsafe.Pointer(&r[0]), dimension(len(r))) != 0 {
throw("random_get failed")
}
}
De esta manera, un usuario puede llamar getRandomData
con una porción de byte y eventualmente se dirigirá al host definido random_get
función. De la misma manera, los usuarios pueden definir sus propios envoltorios para las funciones de host.
Para obtener más información sobre las complejidades de la envoltura de las funciones de WASM en Go, consulte el go:wasmimport
propuesta.
Limitaciones
Mientras el wasip1
El puerto pasa todas las pruebas de biblioteca estándar, hay algunas limitaciones fundamentales notables de la arquitectura WASM que pueden sorprender a los usuarios.
WASM es una arquitectura de un solo roscado sin paralelismo. El planificador aún puede programar las goroutinas para ejecutarse simultáneamente, y el error/error estándar no es bloqueo, por lo que una goroutine puede ejecutar mientras otra lee o escribe, pero cualquier llamada de función de host (como solicitar datos aleatorios con el ejemplo anterior) hará que todas las goroutinas bloqueen hasta que la llamada de la función del host haya regresado.
Una característica faltante notable en el wasip1
API es una implementación completa de enchufes de crimson. wasip1
Solo outline funciones que operan en enchufes ya abiertos, lo que hace que sea imposible admitir algunas de las características más populares de la biblioteca estándar GO, como los servidores HTTP. Anfitriones como Wasmer y Wasmedge implementan extensiones para el wasip1
API, que permite la apertura de enchufes de crimson.
Si bien el compilador GO no implementa estas extensiones, existe una biblioteca de terceros, github.com/stealthrocket/web
que usa go:wasmimport
para permitir el uso de web.Dial
y web.Hear
en anfitriones de WASM apoyados. Esto permite la creación de web/http
servidores y otra funcionalidad relacionada con la crimson al usar este paquete.
El futuro de Wasm in Go
La adición del wasip1/wasm
Port es solo el comienzo de las capacidades de WASM que nos gustaría llevar. Esté atento al rastreador de problemas para las propuestas en torno a la exportación de funciones de GO a WASM (go:wasmexport
), un puerto de 32 bits y una futura compatibilidad de la API WASI.
Complicarse
Si está experimentando y quiere contribuir a WASM y Go, ¡involucrarse! El rastreador de problemas de GO rastrea todo el trabajo en progreso y el canal #Webassembly en el Gophers Slack es un gran lugar para discutir Go y WebAssembly. ¡Esperamos tener noticias tuyas!
Johan Brandhorst-Satzkorn, Julien Fabre, Damian Gryski, Evan Phoenix y Achille Roussel
Este artículo está disponible en
Foto de Neom en Unsplash