1 pontos por GN⁺ 2025-02-16 | 3 comentários | Compartilhar no WhatsApp
  • O Go 1.24 expandiu os recursos relacionados a WebAssembly (Wasm)
  • A diretiva go:wasmexport foi 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 add e depois implementar a função, o host Wasm poderá chamá-la
  • Isso é semelhante à diretiva export do 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 _initialize no lugar
    • O reactor é inicializado por meio da função _initialize, que deve ser chamada antes, em vez da função main
  • Quando usado com runtimes como o Wazero, é possível chamar _initialize e 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:wasmimport foram 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:wasmexport podem criar novas goroutines, mas funções que criam goroutines em background não continuam executando após a função go:wasmexport retornar, 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:wasmimport e go: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:wasmexport no 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

 
click 2025-02-16

Antes de Wasm/gc ser adotado amplamente, acho que é melhor desenvolver para o alvo wasm com uma linguagem sem gc.

 
xguru 2025-02-16

No lançamento do Go 1.24, isso é explicado brevemente, mas parece ser uma atualização muito mais importante.

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

    • Para tentar usar Go WASM no Cloudflare Workers, é necessário ter uma assinatura por causa do tamanho do binário
    • Na última tentativa, o hello-world funcionou, mas algo mais complexo excedeu o limite de tamanho
    • É uma situação lamentável
  • Isso é impressionante. Algo a lembrar:

    • O trabalho de WebAssembly em Go não foi projetado nem implementado pela equipe do Go, mas por voluntários. Portanto, o cronograma depende da disponibilidade desses voluntários
  • 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

    • Seria útil explicar como a nova funcionalidade de WASI melhorou em relação ao que havia antes, além de suportar mais tipos via FFI
    • Segunda pergunta: era possível converter ponteiros em inteiros e então extrair strings e tipos complexos da memória da instância do módulo WASM. Se houver garantia de que a representação binária dos meus tipos em Go é estável, fico pensando se essa forma de passar ponteiros para módulos WASM gerados com goos=wasip1 ainda continua válida
  • Teria 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

    • Isso é igual à forma existente de exportação com cgo. Está seguindo o exemplo anterior. A usabilidade ainda continua fora da linguagem
  • 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

    • O padrão evolui lentamente e, com o aumento da adoção, há o risco de ter que dar suporte para sempre a recursos não padronizados como o WASI