Trabajo con WebAssembly y Go: técnicas avanzadas de integración

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Trabajo con WebAssembly y Go: nivel avanzado



WebAssembly (WASM) abre nuevos horizontes para el desarrollo web, permitiendo ejecutar código de alto rendimiento escrito en lenguajes distintos a JavaScript. Go (Golang), con su compilador a WASM y su modelo simple de concurrencia, es un excelente candidato para crear módulos web complejos. En este artículo exploraremos técnicas avanzadas de integración de Go y WebAssembly: trabajo con memoria, transferencia de estructuras de datos complejas, comunicación bidireccional con JavaScript y optimización del rendimiento.



1. Transferencia de estructuras de datos complejas entre Go y JavaScript



La transferencia básica de números y cadenas a través de syscall/js es simple, pero no es suficiente para aplicaciones reales. Un enfoque avanzado implica la serialización de estructuras complejas (slices, maps, tipos personalizados) en JSON o formato binario.



Serialización mediante JSON

El método más simple y universal es usar encoding/json. Exportas una función que recibe una cadena JSON, la deserializa en una estructura de Go, la procesa y devuelve el resultado como JSON.



// main.gopackage main

import ( "encoding/json" "syscall/js")

type InputData struct { Name string `json:"name"` Value float64 `json:"value"`}

type OutputData struct { Greeting string `json:"greeting"` Square float64 `json:"square"`}

func processData(this js.Value, args []js.Value) interface{} { if len(args) < 1 { return "Error: expected JSON string" } inputJSON := args[0].String()

var input InputData if err := json.Unmarshal([]byte(inputJSON), &input); err != nil { return "Error: " + err.Error() }

output := OutputData{ Greeting: "Hello, " + input.Name, Square: input.Value * input.Value, }

resultJSON, _ := json.Marshal(output) return string(resultJSON)}

func main() { c := make(chan struct{}, 0) js.Global().Set("processData", js.FuncOf(processData)) <-c}


Trabajo directo con memoria (protocolo binario)

Para máximo rendimiento, puedes transferir datos a través de la memoria lineal de WASM. Exportas funciones para escribir/leer de la memoria y pasas punteros (como números enteros) a JavaScript. Este método es más complejo, pero evita la sobrecarga de analizar JSON.



// Exportar función para escribir en memoria//go:wasmexport allocateMemoryfunc allocateMemory(size int) uintptr {    // Usar C.malloc o tu propio asignador    // Devolver el puntero}

//go:wasmexport getMemoryBufferfunc getMemoryBuffer() uintptr { // Devolver el inicio del buffer}


En JavaScript usas WebAssembly.Memory y Uint8Array para leer/escribir en las direcciones obtenidas.



2. Llamar a JavaScript desde Go y manipular el DOM



El paquete syscall/js permite llamar a cualquier función de JavaScript y manipular el DOM. El nivel avanzado implica la creación de interfaces reactivas y el manejo de eventos.



Creación y actualización de elementos del DOM

func appendDiv(this js.Value, args []js.Value) interface{} {    document := js.Global().Get("document")    body := document.Get("body")

newDiv := document.Call("createElement", "div") newDiv.Set("innerHTML", "<h2>Hello from Go WASM!</h2>") newDiv.Get("style").Set("color", "blue") body.Call("appendChild", newDiv) return nil}

func main() { js.Global().Set("appendDiv", js.FuncOf(appendDiv)) select {}}


Manejo de eventos en el lado de Go

func setupClickHandler(this js.Value, args []js.Value) interface{} {    document := js.Global().Get("document")    button := document.Call("getElementById", "myButton")

clickCallback := js.FuncOf(func(this js.Value, args []js

Blogs

Book Recommendations