- O Go 1.24 expandiu os recursos relacionados a WebAssembly (Wasm)
- A diretiva
go:wasmexportfoi adicionada, permitindo chamar funções Go de fora do módulo Wasm - O modo de build “reactor” para WASI também passou a ser suportado, permitindo executar código que permanece ativo por longos períodos
- Com isso, abre-se a possibilidade de expandir aplicações Go em ambientes Wasm com muito mais flexibilidade
WebAssembly and the WebAssembly System Interface
- WebAssembly é um formato binário criado para executar código de baixo nível de alto desempenho em navegadores web
- Hoje ele também é amplamente usado fora dos navegadores, e pode interagir com recursos do sistema por meio do WebAssembly System Interface (WASI)
- O Go começou a oferecer suporte à compilação para Wasm na versão 1.11 com a porta js/wasm, e na versão 1.21 adicionou uma nova porta via
GOOS=wasip1, voltada para a API de chamadas de sistema WASI Preview 1
Exportando funções Go para Wasm com go:wasmexport
- Com a nova diretiva
go:wasmexport, adicionada no Go 1.24, agora é possível expor funções Go como exports para que sejam chamadas de fora do módulo Wasm - Exemplo: ao declarar
//go:wasmexport adde depois implementar a função, o host Wasm poderá chamá-la - Isso é semelhante à diretiva
exportdo cgo, mas implementado com um mecanismo mais simples
Building a WASI Reactor
- Um WASI “reactor” é um módulo WebAssembly que permanece em execução e pode reagir continuamente a eventos ou requisições
- No Go 1.24, o build de WASI reactor é suportado com a opção
-buildmode=c-shared - Essa flag de build instrui o linker a não gerar a função _start (ponto de entrada de módulos de comando), gerando
_initializeno lugar- O reactor é inicializado por meio da função
_initialize, que deve ser chamada antes, em vez da função main
- O reactor é inicializado por meio da função
- Quando usado com runtimes como o Wazero, é possível chamar
_initializee depois reinvocar quantas vezes quiser as funções exportadas - Essa abordagem é útil em ambientes que usam Wasm como mecanismo de plugin ou extensão da aplicação
Suporte mais rico a tipos entre host e cliente
- No Go 1.24, as restrições sobre tipos de parâmetros e retorno de funções chamadas com
go:wasmimportforam flexibilizadas - Por exemplo, agora é possível passar bool, string, ponteiro para int32, ponteiro para struct etc.
- Ainda assim, continuam existindo limitações, como diferenças entre ambientes de 64 e 32 bits
- Isso torna a escrita de aplicações Go Wasm mais natural e conveniente, eliminando conversões de tipo desnecessárias
Limitações
- Wasm é uma arquitetura single-threaded, sem processamento paralelo
- Funções
go:wasmexportpodem criar novas goroutines, mas funções que criam goroutines em background não continuam executando após a funçãogo:wasmexportretornar, até que o módulo Wasm baseado em Go seja chamado novamente - Algumas restrições de tipo foram flexibilizadas, mas ainda há limites para os tipos que podem ser usados com funções
go:wasmimportego:wasmexport- Ainda existem restrições para passar tipos compostos que incluem ponteiros
Conclusão
- O build de WASI reactor e a adição de
go:wasmexportno Go 1.24 são melhorias que ampliam significativamente o ecossistema Wasm do Go - Isso permite que desenvolvedores criem uma variedade maior de aplicações Wasm baseadas em Go, abrindo novas possibilidades para o Go no ecossistema Wasm
3 comentários
Antes de
Wasm/gcser adotado amplamente, acho que é melhor desenvolver para o alvo wasm com uma linguagem sem gc.No lançamento do Go 1.24, isso é explicado brevemente, mas parece ser uma atualização muito mais importante.
Opiniões no Hacker News
Há um problema sério com o tamanho muito grande dos binários WASM gerados por Go. O TinyGo contorna isso, mas compila devagar e exige cuidado na escolha das bibliotecas. Para superar os dois problemas, é preciso muita paciência
Isso é impressionante. Algo a lembrar:
Não lembro bem se, antes do Go 1.24, já não era possível exportar funções de Go para JS. Lembro de já ter chamado a partir de JS funções exportadas de Go sem problemas
goos=wasip1ainda continua válidaTeria parecido mais "Go-like" exportar todas as funções do pacote principal que começam com letra maiúscula. Como exportação já funciona assim normalmente na linguagem, talvez fosse melhor usar uma diretiva do compilador apenas quando fosse necessário nomear explicitamente algo que começa com minúscula
Não há menção ao trabalho com o modelo de componentes do WASM
Fico curioso sobre como o garbage collector do Go e do WASM funciona
Queria que existisse uma linguagem de baixo nível com tipagem forte e excelente suporte a WASM
Fico me perguntando como se depura um módulo WASM em execução a partir do programa host
Tenho receio de que o desejo por mais funcionalidades de WASM acabe prejudicando irreversivelmente esse ecossistema ainda jovem. A maior parte do que o Go adicionou ao WASM poderia ter sido feita de forma nativa se a proposta do modelo de componentes já tivesse sido incorporada