WebAssembly excursion with Go

Boris Djurdjevic
May 19, 2018 · 2 min read

This post shows you how easily it is to compile a WebAssembly module using Go with the latest patches as language.

I’ve been watching the WebAssembly (Wasm) support issue for Go for a long time without trying any patches out. WebAssembly support would be a great benefit for the Go and web community as it allows different languages and technologies to be used crossplatform and sandboxed in a standard webbrowser. Completly without Flash, Silverlight and all other painful stuff. Even without transpiling to JavaScript. It’s a real solution, not a workaround.

Building Go

Building Go is pretty easy and takes less than five minutes on my mid-end laptop. Just clone the repository and run the build script. That’s it. But not all patches are merged into upstream yet so I will clone Richard Musiol s repository, as he is the leading one who is porting Go to Wasm and will maintain the port:

$ git clone git@github.com:neelance/go.git newgo
$ cd newgo/src/
$ git rev-parse HEAD
d7841c75357e82fb6b880bbc84d36bd28d825847
$ git checkout wasm-wip
$ ./all.bash
$ export PATH=/home/djboris/newgo/bin:$PATH
$ go version
go version devel +d7841c7535 Sat May 19 13:15:47 2018 +0200 linux/amd64

Go code for WebAssembly

This example code should be compiled to a WebAssemble module:

package mainimport "fmt"func main() {
fmt.Println(Add(21, 21))
}
func Add(a, b int) int {
return a + b
}

As crosscompiling code for WebAssembly is exactly the same as for other architectures in Go, you must only set two environment variables and run the usual build command:

$ GOARCH=wasm GOOS=js go build -o main.wasm main.go

This will generate main.wasm which will be loaded and executed by the browser. Its MIME type is application/wasm so it must be served with the according Content-Type or the browser will complain.

Combining the things

My first try was a week ago on a older revision of the wasm-wip branch. So Firefox printed an error to the console when I tried to execute it using the MDN examples:

TypeError: import object field 'go' is not an Object

Sadly the main.wasm binary had imports which couldn’t be satisfied:

Image for post
wasm-dump -x main.wasm # go get github.com/go-interpreter/wagon/cmd/wasm-dump

After that I tried to mock the non existing functions for the importObject but before I had a running version, a useful commit came in which fitted the gap. Combining the provided wasm_exec.js with the following html does the trick.

<html>
<body>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch('main.wasm'), go.importObject).then(function(dat) {
go.run(dat.instance);
});
</script>
</body>
</html>

After serving wasm_exec.js, index.htmland main.wasm, the developer console said 42. The WebAssembly module was executed and my first first WebAssembly excursion was successful too :)

Acknowledgement

I would like to thank Richard Musiol for his great work making WebAssembly a build target for Go!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store