Gracias a WebAssembly podemos ejecutar código de otros lenguajes de programación desde el navegador web con JavaScript. La ventaja de WASM es que, aparte de ser rápido, permite programar en otro lenguaje y aprovechar las librerías presentes en el mismo.
Personalmente he usado Golang con WebAssembly para crear un generador de credenciales, códigos QR y códigos de barras. Todo el procesamiento y generación de imágenes se hace con Go, para luego exportar los resultados a JavaScript.
En este post voy a documentar cómo exportar un arreglo de tipo byte ([]byte) de Go a un Uint8Array de JavaScript, ya que, como te lo dije anteriormente, esto sirve cuando creamos un archivo binario con Go y queremos exportarlo a JavaScript.
Además, un Uint8Array
sí puede ser transportado a través de un WebWorker usando el structured clone algorithm.
Exponer función
Yo expongo la función así:
Aquí Global()
va a devolver el ámbito global desde donde se invoca a la función de WASM.
Si estamos en un WebWorker será self, si estamos en el DOM será window y puede devolver otra cosa según el entorno.
Invocar función que devuelve Uint8Array []byte
Fíjate en que la estoy exponiendo como generarCodigos
así que podré invocarla desde JavaScript con self.generarCodigos()
, y que realmente la función de Go se llama GenerarCodigos
cuyo código dejo a continuación:
Realmente el cuerpo de la función no es relevante. Solo estoy probando si estoy recibiendo correctamente el arreglo de objetos desde JavaScript. La parte importante viene a continuación:
Tengo el siguiente arreglo de bytes que representan un PDF:
Lo importante es que bytesQueConformanElPDF
es un []byte
.
Copiar arreglo de []byte con js.CopyBytesToJS
Ahora vamos a copiar el arreglo de bytes a JavaScript para devolverlo como resultado de la invocación. Hacemos un nuevo Uint8Array
cuya longitud será la misma que la longitud del arreglo que tenemos en Go y que podemos obtener con len
:
Ese fragmento de código es el equivalente a new Uint8Array()
de JavaScript. Luego invocamos a js.CopyBytesToJS
indicando el destino y el origen. El destino será el Uint8Array
que definimos desde Go usando New
, y el origen será el []byte
que tenemos en Go, así:
Y ahora vamos a tener ese Uint8Array como resultado de la invocación de la función. En mi caso lo tengo con Comlink y un worker expuestos a través de una Store de Vue, así que lo uso así:
Aquí, resultado
es el Uint8Array que devolvió la invocación a WebAssembly. En el ejemplo lo estoy descargando pero podemos hacer más cosas.
Conclusión
Así de simple podemos invocar a una función de Go desde JavaScript pasando y recibiendo parámetros complejos, ya que invocamos a la función con un arreglo de objetos que podemos leer en Go, y luego Go nos devuelve un Uint8Array.
Nota importante: aunque aquí uso “Go” y “JavaScript” como si se ejecutaran en entornos separados la verdad es que ambos se van a ejecutar en el navegador web gracias a WebAssembly.