Go no WebAssembly: Caminhos para Navegador, WASI e Embarcado
Go compila para WebAssembly, mas WebAssembly não é um único modelo de implantação.
Busque em todas as páginas da documentação
Go compila para WebAssembly, mas WebAssembly não é um único modelo de implantação.
A mesma linguagem alcança o DOM do navegador, hosts WASI do lado do servidor e placas com restrição de flash através de diferentes pares GOOS/GOARCH e, às vezes, um compilador diferente (TinyGo).
Escolher o caminho antecipadamente determina o tamanho do binário, a cobertura da stdlib e qual runtime de host você incorpora.
js/wasm), servidor WASI (wasip1/wasm) e embarcado/restrito (TinyGo) - cada uma com diferentes syscalls, hosts e orçamentos de tamanho.syscall/js onde um módulo WASI deveria rodar headless.syscall/js, WASI preview 1 (wasip1), runtime de host, superfície de importação, TinyGo -target, memória linear..wasm, FaaS/workers de borda, ou WASM adjacente a firmware em dispositivos.net/http é portado sem alterações.syscall/js, alvos de placa TinyGo.WebAssembly é um formato de bytecode portátil com um modelo de memória linear e uma ABI de importação/exportação.
Go não emite um OS autônomo - ele emite um módulo .wasm que importa funções do host para I/O (arquivos, relógios, aleatoriedade, DOM, sockets).
O alvo do compilador Go (GOOS + GOARCH, ou TinyGo -target) decide quais imports o linker espera e quais pacotes da stdlib compilam.
Caminho do navegador (GOOS=js GOARCH=wasm): Go roda dentro de um host JavaScript.
O modelo histórico usa syscall/js para chamar APIs DOM e registrar callbacks.
O host carrega wasm_exec.js (de GOROOT/misc/wasm) para implementar os imports JS do runtime Go.
Este caminho é para UIs interativas e demos de WASM-na-aba, não para servidores headless.
Caminho WASI (GOOS=wasip1 GOARCH=wasm): Go compila para um módulo headless que fala WASI Preview 1 - uma superfície de capacidade POSIX-ish (arquivos, ambiente, relógios, aleatoriedade).
Você roda o .wasm com um runtime de host como wasmtime, wazero, ou Spin.
Este é o modelo mental padrão para "binário Go, mas WASM portátil" em servidores, sandboxes de CI e plataformas de borda.
Caminho embarcado / restrito (TinyGo): TinyGo é um compilador separado que tem como alvo microcontroladores (ARM Cortex-M, AVR, RISC-V) e também wasm com binários muito menores.
Ele troca a completude da stdlib e recursos de tempo de compilação por orçamentos de flash/RAM.
Use-o quando o dispositivo ou o tamanho do download WASM for a restrição rígida.
Seu código Go
|
+-- go build (gc) -- GOOS=js GOARCH=wasm --> navegador + syscall/js
|
+-- go build (gc) -- GOOS=wasip1 GOARCH=wasm --> WASI .wasm + runtime de host
|
+-- tinygo build -- -target=... --> Firmware de MCU ou WASM minúsculo
A superfície de importação é o contrato entre o módulo e o host.
Módulos de navegador importam shims de runtime JS; módulos WASI importam funções wasi_snapshot_preview1; WASM TinyGo pode importar um conjunto mínimo ajustado para tamanho.
Se você compilar para wasip1 mas carregar o módulo em um navegador sem polyfills WASI, a instanciação falha na resolução de importação.
Memória e runtime: O Go WASM completo inclui o scheduler e o GC no módulo.
A memória linear cresce à medida que o heap cresce.
Go 1.26 aloca o heap em pedaços menores para heaps abaixo de 16 MiB, o que reduz materialmente a memória ociosa para microsserviços WASI e filtros pequenos.
TinyGo usa um runtime diferente com memória base menor, ao custo de limites de goroutine/reflexão.
Tags de build e divisões de arquivos: O código do navegador geralmente vive atrás de //go:build js && wasm para que pacotes de servidor não puxem syscall/js para builds WASI.
O código WASI usa //go:build wasip1 (ou o build padrão não-JS) e deve evitar pacotes específicos do DOM completamente.
Runtimes de host diferem em ergonomia de incorporação:
| Abordagem | Força | Fraqueza | Melhor Ajuste |
|---|---|---|---|
js/wasm + syscall/js | Acesso DOM a partir de Go | Binário grande, cola JS necessária | Demos de navegador, widgets UI WASM |
wasip1/wasm (toolchain gc) | Stdlib completa, go build familiar | Módulos de múltiplos MiB típicos | Plugins de servidor, CLIs portáteis, incorporação wazero |
| TinyGo WASM / MCU | Binários muito pequenos | Stdlib incompleta, menos bibliotecas | Placas embarcadas, WASM de borda com tamanho limitado |
Pipelines WASM poliglota: Equipes frequentemente escrevem caminhos críticos em Rust para tamanho mínimo e orquestram em Go via wazero.
As melhorias de heap do Go 1.26 reduzem a diferença para pequenos serviços que se beneficiam de permanecer em uma única linguagem.
Segurança e sandboxing: I/O baseado em capacidade WASI se encaixa melhor em hosts multi-inquilino do que dar aos módulos acesso bruto ao sistema de arquivos do host.
Pré-abra diretórios e variáveis de ambiente explicitamente na configuração do wasmtime/wazero em vez de assumir paridade POSIX.
Estratégia de CI: Matrizes de build devem incluir GOOS=wasip1 GOARCH=wasm (e TinyGo se usado) ao lado de linux/amd64.
Execute módulos com wasmtime run ou wazero em testes de integração para capturar imports ausentes precocemente.
Consciência de depreciação: Go WASM focado em navegador que depende de syscall/js é um nicho especializado.
Trabalhos de servidor Greenfield devem usar wasip1 por padrão, a menos que a ponte DOM seja o requisito real.
"Um .wasm roda em qualquer lugar" - Os conjuntos de imports diferem por alvo; um módulo de navegador não é intercambiável com um módulo WASI sem recompilação e um host correspondente.
"TinyGo é só -ldflags -s -w para Go" - TinyGo usa um compilador e runtime diferentes; o suporte à linguagem e a cobertura da stdlib divergem de forma material.
"WASI equivale a Linux completo" - WASI preview 1 cobre arquivos, relógios e aleatoriedade, não uma stack de rede completa em todo host.
Verifique as extensões de socket e HTTP do seu runtime antes de portar servidores net/http literalmente.
Mantenha builds de navegador isolados atrás de build tags.
Use GOOS=wasip1 e GOARCH=wasm com a toolchain Go padrão.
Isso produz um módulo WASI Preview 1 que você executa com wasmtime, wazero ou hosts de borda compatíveis.
Quando Go precisa chamar APIs do navegador (DOM, fetch, canvas) via syscall/js.
Para cargas de trabalho apenas de computação no navegador, considere compilar para WASI e usar um host com WASI-in-JS, ou mantenha o caminho crítico em JavaScript/TypeScript.
A rede depende do runtime de host e da versão WASI.
Muitos hosts expõem sockets através de extensões; Spin mapeia gatilhos HTTP diretamente.
Prototipe no seu host de destino antes de assumir que ListenAndServe funciona sem alterações.
TinyGo é uma toolchain independente baseada em LLVM focada em binários pequenos.
Ele compartilha a sintaxe Go, mas não garante que todos os pacotes da stdlib ou padrões de reflexão funcionem.
Módulos Go completos incluem runtime, scheduler e GC.
TinyGo e minimização de importação encolhem o tamanho; o chunking de heap do Go 1.26 reduz o overhead de memória, mas não necessariamente o tamanho inicial de download sem -ldflags=-s -w.
wazero quando o embedder já é Go (sem cgo, CI fácil).
wasmtime para paridade CLI/dev e ampla cobertura WASI.
Spin ao implantar manipuladores HTTP para Fermyon Cloud ou runtimes de borda compatíveis.
Não. wasm_exec.js é para o alvo js/wasm.
Módulos WASI rodam sob um runtime WASM que fornece imports WASI, não o shim JS do navegador.
Coloque código exclusivo do navegador em arquivos com tag js && wasm, lógica compartilhada em builds padrão e mantenha pacotes main separados por alvo se os imports divergirem.
Sim, para memória: incrementos menores de heap ajudam cargas de trabalho abaixo de 16 MiB.
O compilador também sempre usa certas extensões de instrução WASM (configurações de signext, satconv são ignoradas).
TinyGo com um -target explícito para sua placa (por exemplo, arduino, pico, variantes cortex-m).
go build completo não emite imagens de firmware para esses dispositivos.
Versões de Stack: Esta página foi escrita para Go 1.26.x (padrão Green Tea GC, modernizadores go fix - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação), e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026