Wasm Builders 🧱

Cover image for Golang with WebAssembly on Browser
Kirtee Prajapati
Kirtee Prajapati

Posted on

Golang with WebAssembly on Browser

In this tutorial, we will cross compile a Go application to WebAssembly and run it on the browser.

We will create a simple application that is used to format JSON.

Considering the system to be Ubuntu

Environment setup

1. Install Golang

sudo snap install go         # version 1.18, or
sudo apt  install golang-go  # version 2:1.13~1ubuntu2
sudo apt  install gccgo-go   # version 2:1.13~1ubuntu2

#See 'snap info go' for additional versions.
Enter fullscreen mode Exit fullscreen mode

2. Install TinyGo

wget https://github.com/tinygo-org/tinygo/releases/download/v0.22.0/tinygo_0.22.0_amd64.deb
sudo dpkg -i tinygo_0.22.0_amd64.deb
Enter fullscreen mode Exit fullscreen mode

Verify Installations

the output should be somthing in numbers if installed successfully

$ tinygo version
$ go version
Enter fullscreen mode Exit fullscreen mode

Image description

Since we are not using any template for file structure.
So create the following directory structure inside the Documents directory.

Image description

Inside ~/Documents/webassembly/cmd/wasm/main.go add the following Hello World program in Go

package main

import (  
    "fmt"
)

func main() {  
    fmt.Println("Go Web Assembly")
}
Enter fullscreen mode Exit fullscreen mode

To cross compile the above Go program into WebAssembly run the following inside ~/Documents/webassembly/cmd/wasm/:

GOOS=js GOARCH=wasm go build -o  ../../assets/json.wasm
Enter fullscreen mode Exit fullscreen mode

The above command uses js as GOOS and wasm.

Running it will create the WebAssembly module json.wasm in the assets directory.

Image description

Your Folder should look like this

We can execute .wasm as wasm binary is supposed to be run inside a browser sandbox.

So to achive that some JavaScript glue code is needed to import the WebAssembly Module.

Javascript Glue

cd ~/
git clone https://github.com/golang/go.git
Enter fullscreen mode Exit fullscreen mode

Glue Code is already available in the Go installation.
To copy paste that to ~/Documents/webassembly/assets/ directory run the following command

cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" ~/Documents/webassembly/assets/  
Enter fullscreen mode Exit fullscreen mode

or you can manually also copy paste that.

assets folder will contain all the HTML, JavaScript, and wasm code which will be served using a web server later.

Create Index.html inside assets directory

$ touch index.html
Enter fullscreen mode Exit fullscreen mode

and paste the below code inside it

<html>  
    <head>
        <meta charset="utf-8"/>
        <script src="wasm_exec.js"></script>
        <script>
            const go = new Go();
            WebAssembly.instantiateStreaming(fetch("json.wasm"), go.importObject).then((result) => {
                go.run(result.instance);
            });
        </script>
    </head>
    <body></body>
</html>  
Enter fullscreen mode Exit fullscreen mode

The current directory structure after creating index.html is provided below.

Image description

Let's understand what's going inside .html file

  • The instantiateStreaming function is used to initialize our json.wasm WebAssembly module.

  • It returns a WebAssembly instance which contains the list of WebAssembly functions that can be called from JavaScript.

WebServer

Create a file named main.go inside the server directory.

Image description

your directory uptill now should look like this.

inside ~/Documents/webassembly/cmd/server/main.go add the following code.

package main

import (  
    "fmt"
    "net/http"
)

func main() {  
    err := http.ListenAndServe(":9090", http.FileServer(http.Dir("../../assets")))
    if err != nil {
        fmt.Println("Failed to start server", err)
        return
    }
}
Enter fullscreen mode Exit fullscreen mode

Image description

Let's run the server and see our first WebAssembly program running.

$ cd ~/Documents/webassembly/cmd/server/  
$ go run main.go  
Enter fullscreen mode Exit fullscreen mode

Program creates a file server listening at port 9090 visit http://localhost:9090/

Yeahh!! we got our server designed with go and webassembly.

But You can see that the page is empty.
You can create the UI for the page for making it more appealing.

Image description

References:

  1. https://golangbot.com/webassembly-using-go/
  2. https://enarx.dev/docs/WebAssembly/Golang
  3. https://tinygo.org/getting-started/install/linux/#ubuntu-debian
  4. https://github.com/golang/go/wiki/WebAssembly#getting-started
  5. https://github.com/golang/go/blob/master/misc/wasm/wasm_exec.js?source=post_page---------------------------

Top comments (1)

Collapse
 
omdev74 profile image
Om dev

I get this error
WebAssembly.instantiateStreaming(): expected magic word 00 61 73 6d, found 4d 5a 90 00 @+0