Go en WebAssembly: Rutas para Navegador, WASI y Embebido
Go compila a WebAssembly, pero WebAssembly no es un único modelo de despliegue.
Busca en todas las páginas de la documentación
Go compila a WebAssembly, pero WebAssembly no es un único modelo de despliegue.
El mismo lenguaje alcanza el DOM del navegador, hosts WASI del lado del servidor y placas con memoria flash limitada a través de diferentes pares GOOS/GOARCH y, a veces, un compilador diferente (TinyGo).
Elegir la ruta temprano determina el tamaño del binario, la cobertura de la librería estándar y qué runtime anfitrión se embebe.
js/wasm), servidor WASI (wasip1/wasm) y embebido/restringido (TinyGo), cada uno con diferentes llamadas al sistema, hosts y presupuestos de tamaño.syscall/js donde un módulo WASI debería ejecutarse sin cabeza.syscall/js, WASI preview 1 (wasip1), runtime anfitrión, superficie de importación, TinyGo -target, memoria lineal..wasm, FaaS/workers de borde, o WASM adyacente a firmware en dispositivos.reflect; no todos los patrones de net/http se portan sin cambios.syscall/js, objetivos de placa TinyGo.WebAssembly es un formato de bytecode portable con un modelo de memoria lineal y una ABI de importación/exportación.
Go no emite un sistema operativo independiente; emite un módulo .wasm que importa funciones del host para E/S (archivos, relojes, aleatoriedad, DOM, sockets).
El objetivo del compilador de Go (GOOS + GOARCH, o TinyGo -target) decide qué importaciones espera el enlazador y qué paquetes de la librería estándar compilan.
Ruta del navegador (GOOS=js GOARCH=wasm): Go se ejecuta dentro de un host JavaScript.
El modelo histórico usa syscall/js para llamar a las APIs del DOM y registrar callbacks.
El host carga wasm_exec.js (desde GOROOT/misc/wasm) para implementar las importaciones de JS del runtime de Go.
Esta ruta es para interfaces de usuario interactivas y demos de WASM en la pestaña, no para servidores sin cabeza.
Ruta WASI (GOOS=wasip1 GOARCH=wasm): Go compila a un módulo sin cabeza que habla WASI Preview 1, una superficie de capacidades similar a POSIX (archivos, entorno, relojes, aleatoriedad).
Ejecutas el .wasm con un runtime anfitrión como wasmtime, wazero o Spin.
Este es el modelo mental por defecto para "binario de Go, pero WASM portable" en servidores, sandboxes de CI y plataformas de borde.
Ruta embebida / restringida (TinyGo): TinyGo es un compilador separado que tiene como objetivo microcontroladores (ARM Cortex-M, AVR, RISC-V) y también wasm con binarios mucho más pequeños.
Cambia la completitud de la librería estándar y las características de tiempo de compilación por presupuestos de memoria flash/RAM.
Úsalo cuando el dispositivo o el tamaño de descarga de WASM sea la restricción principal.
Tu código fuente Go
|
+-- go build (gc) -- GOOS=js GOARCH=wasm --> navegador + syscall/js
|
+-- go build (gc) -- GOOS=wasip1 GOARCH=wasm --> WASI .wasm + runtime anfitrión
|
+-- tinygo build -- -target=... --> Firmware MCU o WASM diminuto
La superficie de importación es el contrato entre el módulo y el host.
Los módulos del navegador importan shims del runtime de JS; los módulos WASI importan funciones de wasi_snapshot_preview1; WASM de TinyGo puede importar un conjunto mínimo ajustado para el tamaño.
Si compilas para wasip1 pero cargas el módulo en un navegador sin polyfills WASI, la instanciación falla en la resolución de importaciones.
Memoria y runtime: El WASM completo de Go incluye el planificador y el GC de Go en el módulo.
La memoria lineal crece a medida que crece el heap.
Go 1.26 asigna el heap en trozos más pequeños para heaps menores a 16 MiB, lo que reduce materialmente la memoria inactiva para microservicios WASI y filtros pequeños.
TinyGo usa un runtime diferente con menor memoria base, a costa de límites de goroutines/reflexión.
Tags de compilación y divisiones de archivos: El código del navegador a menudo vive detrás de //go:build js && wasm para que los paquetes del servidor no arrastren syscall/js a las compilaciones WASI.
El código WASI usa //go:build wasip1 (o la compilación por defecto que no es JS) y debe evitar completamente los paquetes específicos del DOM.
Los runtimes anfitriones difieren en la ergonomía de embebido:
| Enfoque | Fortaleza | Debilidad | Mejor Ajuste |
|---|---|---|---|
js/wasm + syscall/js | Acceso al DOM desde Go | Binario grande, requiere pegamento JS | Demos de navegador, widgets de UI WASM |
wasip1/wasm (toolchain gc) | Librería estándar completa, go build familiar | Módulos de varios MiB típicos | Plugins de servidor, CLIs portátiles, embebido wazero |
| TinyGo WASM / MCU | Binarios muy pequeños | Librería estándar incompleta, menos bibliotecas | Placas embebidas, WASM de borde con tamaño limitado |
Pipelines WASM políglotas: Los equipos a menudo escriben rutas críticas en Rust para un tamaño mínimo y orquestan en Go a través de wazero.
Las mejoras de heap de Go 1.26 reducen la brecha para servicios pequeños que se benefician de permanecer en un solo idioma.
Seguridad y sandboxing: La E/S basada en capacidades de WASI se ajusta mejor a hosts multitenant que dar a los módulos acceso crudo al sistema de archivos del host.
Abre directorios y variables de entorno explícitamente en la configuración de wasmtime/wazero en lugar de asumir paridad POSIX.
Estrategia de CI: Las matrices de compilación deben incluir GOOS=wasip1 GOARCH=wasm (y TinyGo si se usa) junto con linux/amd64.
Ejecuta módulos con wasmtime run o wazero en pruebas de integración para detectar importaciones faltantes temprano.
Conciencia de deprecación: El WASM de Go enfocado en el navegador que depende de syscall/js es un nicho especializado.
El nuevo desarrollo de servidores debe usar wasip1 por defecto, a menos que el puente DOM sea el requisito real.
"Un .wasm se ejecuta en todas partes" - Los conjuntos de importación difieren por objetivo; un módulo de navegador no es intercambiable con un módulo WASI sin recompilación y un host coincidente.
"TinyGo es solo -ldflags -s -w para Go" - TinyGo usa un compilador y runtime diferentes; el soporte del lenguaje y la cobertura de la librería estándar difieren materialmente.
"WASI equivale a Linux completo" - WASI preview 1 cubre archivos, relojes y aleatoriedad, no una pila de red completa en cada host.
Verifica las extensiones de socket y HTTP de tu runtime antes de portar servidores net/http sin cambios.
Mantén los builds del navegador aislados detrás de tags de compilación.
Usa GOOS=wasip1 y GOARCH=wasm con la toolchain estándar de Go.
Esto produce un módulo WASI Preview 1 que ejecutas con wasmtime, wazero o hosts de borde compatibles.
Cuando Go necesita llamar a APIs del navegador (DOM, fetch, canvas) a través de syscall/js.
Para cargas de trabajo solo de cómputo en el navegador, considera compilar a WASI y usar un host con WASI en JS, o mantén la ruta crítica en JavaScript/TypeScript.
La red depende del runtime anfitrión y la versión de WASI.
Muchos hosts exponen sockets a través de extensiones; Spin mapea disparadores HTTP directamente.
Prototipa en tu host de destino antes de asumir que ListenAndServe funciona sin cambios.
TinyGo es una toolchain independiente basada en LLVM enfocada en binarios pequeños.
Comparte la sintaxis de Go pero no garantiza que todos los paquetes de la librería estándar o patrones de reflexión funcionen.
Los módulos completos de Go incluyen el runtime, el planificador y el GC.
TinyGo y la minimización de importaciones reducen el tamaño; la fragmentación del heap de Go 1.26 reduce la sobrecarga de memoria pero no necesariamente el tamaño de descarga inicial sin -ldflags=-s -w.
wazero cuando el embebedor ya es Go (sin cgo, CI fácil).
wasmtime para paridad CLI/dev y amplia cobertura WASI.
Spin al desplegar manejadores HTTP en Fermyon Cloud o runtimes de borde compatibles.
No. wasm_exec.js es para el objetivo js/wasm.
Los módulos WASI se ejecutan bajo un runtime WASM que proporciona importaciones WASI, no el shim JS del navegador.
Coloca el código exclusivo del navegador en archivos etiquetados js && wasm, la lógica compartida en compilaciones predeterminadas, y mantén los paquetes main separados por objetivo si las importaciones divergen.
Sí, para la memoria: incrementos de heap más pequeños ayudan a cargas de trabajo menores a 16 MiB.
El compilador también usa siempre ciertas extensiones de instrucciones WASM (se ignoran las configuraciones de signext, satconv).
TinyGo con un -target explícito para tu placa (por ejemplo, arduino, pico, variantes de cortex-m).
go build completo no emite imágenes de firmware para esos dispositivos.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado Green Tea GC, modernizadores de go fix - verificar parche en build), chi (última - verificar en build), gin (última - verificar en build), echo (última - verificar en build), google.golang.org/grpc (última - verificar en build), sigs.k8s.io/controller-runtime (última - verificar en build), kubebuilder (última - verificar en build), tinygo (última - verificar objetivos de placa en build), wazero (última - verificar en build), y golangci-lint (última - verificar conjunto de linters en build).
Revisado por Chris St. John·Última actualización: 16 jul 2026