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.
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
Verify Installations
the output should be somthing in numbers if installed successfully
$ tinygo version
$ go version
Since we are not using any template for file structure.
So create the following directory structure inside the Documents directory.
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")
}
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
The above command uses js as GOOS and wasm.
Running it will create the WebAssembly module json.wasm in the assets directory.
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
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/
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
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>
The current directory structure after creating index.html is provided below.
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.
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
}
}
Let's run the server and see our first WebAssembly program running.
$ cd ~/Documents/webassembly/cmd/server/
$ go run main.go
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.
References:
- https://golangbot.com/webassembly-using-go/
- https://enarx.dev/docs/WebAssembly/Golang
- https://tinygo.org/getting-started/install/linux/#ubuntu-debian
- https://github.com/golang/go/wiki/WebAssembly#getting-started
- https://github.com/golang/go/blob/master/misc/wasm/wasm_exec.js?source=post_page---------------------------
Top comments (1)
I get this error
WebAssembly.instantiateStreaming(): expected magic word 00 61 73 6d, found 4d 5a 90 00 @+0