Golang is syntactically similar to C, but with memory safety, Garbage Collection and CSP-style concurrency. - Wikipedia

We can compile Go into WebAssembly. This means we can write channels in Golang and run them on the browser.

WebAssembly in Golang is still in its early days. 🦄

Golang is very simple to write. Thus it is easy to compile the existing application straight into WebAssembly modules provided they don't have any file path or system level features which will not be available for WebAssembly during its runtime.

Hello World

Create a folder called go-wasm with child folders out and go;

go-wasm/
|__ out/
|__ go/

Create a file called main.go inside the go folder and enter the following contents:

packagemainfuncmain(){println("Hello World!!!")}

Run the go file with go run go/main.go. This will print Hello World. Ain't that easy.

Now we can compile this into WebAssembly module and run as a WebAssembly.

GOOS=js GOARCH=wasm go build -o out/main.wasm go/main.go

This will generate the main.wasm inside the out folder. Unlike Rust, Golang does not generate any binding file. We can use the binding file available from the TinyGo's official repository here.

Download the file and move it inside the out directory.

Create an index.html file inside the out directory and add the following contents:

Any performance WebAssembly might give, it is not desirable to have it if the modules are huge.

Don't worry we have Teeny TinyGO.

Tiny Go

The TinyGo is a project built to take Golang into microcontrollers and modern web browsers. They have a brand new compiler that compiles based on LLVM. With TinyGo we can generate teeny tiny libraries that are optimized to execute in the chips.

Since we have LLVM underneath we can tweak it further using the -opt flag. The maximum size optimization is obtained with the -opt=z flag and TinyGo uses this by default. Because those tiny devices have limited memory.

Keep tuning in the next post, let us re-create the classic Dev's offline page using TinyGo and WebAssembly.

I hope this gives you a motivation to start your awesome WebAssembly journey. If you have any questions/suggestions/feel that I missed something feel free to add a comment.

Great post. Couldn't work around the first example though. Apparently this works different on Linux archs because here it is suggested we generate wasm_exec.js by doing cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .. That did the trick for me.

tinygo bundle sizes look very promising, however didn't work for me. After compiling to main.wasm with tinygo I get the following error in Chrome console: 'Import #0 module="env" error: module is not an object or function'. What could be wrong here?