Golang: Are we WebAssembly Yet?
For the past several months, I’ve been working on an open source project called Waxosuit — a secure, cloud-native host runtime for WebAssembly modules. This project is written in Rust and takes advantage of a number of incredibly powerful Rust libraries and tools for manipulating and interpreting WebAssembly modules.
Since before I wrote the first line of code, I’ve always anticipated creating a Go SDK for building guest modules (currently Waxosuit only has a Rust guest SDK). I started looking into the Wasm ecosystem for Go and was surprised to discover a number of gaps.
When I went searching for examples on how to create Wasm modules in Go, most of what I found involved interaction with the browser. Released in Go 1.11, there’s the syscall/js package that provides a means of interaction with the host runtime environment — if the host environment is a browser.
Right at the top of that documentation page, there’s a disclaimer indicating that the package is experimental and should not be used in production and is only there to make tests pass.
Today there are two main ways you can compile Go into Wasm modules — through the regular Go compiler and through TinyGo. Phil Kedy, a colleague of mine who is far more immersed in the Go community than myself was also looking into this and did some digging on Go’s ability to produce clean, functioning Wasm modules.
The first thing we noticed is that building using the standard Go compiler has no support for imports from arbitrary namespaces. The only imports Go will support are the ones that come from the default
env namespace. This is not compliant with the Wasm 1.0 specification and is one of the key reasons why I can’t (yet) produce a Go SDK for Waxosuit — Go can’t produce a Wasm module that complies with the Wascap spec (which requires clean Wasm 1.0 compliance). Go also produces enormous Wasm modules. There are tools to trim them, but it’s nothing like what you get with C++ or Rust.
Phil had a chance to talk to the folks building TinyGo recently at GopherCon. This project looks to be more in line with what I’ve been looking for. Their compiled output is far smaller and a more pure WebAssembly target. It also will support proper namespaces (Phil submitted a PR to add that feature). However, TinyGo doesn’t currently support reflection, which means it can’t compile a whole family of dependencies, including Google’s protobuf (the binary encoding format I use for marshaling data across the guest/host boundary).
In short, Go’s WebAssembly support seems pretty early days (and self-labeled as experimental) and not ready for production use. That immaturity is even more visible when you look at Go’s support for non-browser host runtimes. This doesn’t mean I’m stuck twiddling my thumbs waiting for this situation to improve — I’ve got more work than I have time working on Waxosuit.
I am hoping that the Go community continues to investigate and embrace WebAssembly, not because I have any desire to build browser-based apps in Go, but because I believe that WebAssembly’s true home is in the cloud, and Go is often considered the “de facto cloud language.”
As Go’s Wasm capabilities mature, I’ll continue to re-evaluate it and once it feels like something that’s stable enough on which to build a foundation, I’ll get to work on providing a Go guest SDK for Waxosuit so people can build secure, boilerplate-free, cloud native services and functions in Go.