Getting started with Web Assembly and Go for frontend developers.

Liron Navon
codesight
Published in
4 min readMay 26, 2019

Web assembly is picking up and is now supported in most modern browsers (85%), and it’s a good time to get started if you haven’t yet, get started with Go (Golang for search engines) is really easy, and no go experience is required for this tutorial — you can read more about how WASM works and why use it here.

To get started we should first have GO installed, you can check the instructions here.
Once we have Go installed, we need to create a new directory, and in it create a few initial files (you can simply clone the repo):

We use the WebAssembly.instantiateStreaming function to initiate the wasm code, and use the go loader to run our wasm code.

Our main.go file is simple: we import the fmt package which has similar functionality to console.log (for our use), and by default, it will print to our console, and we have a function named main, every Go project starts with the main function, and once the code is loaded through wasm, this function will run and print “Hello, WebAssembly!” to the console.

Now that we have the initial files, we need to get the “wasm_exec.js” file, which will allow us to load the wasm code for go (this is what gives us the Go class we use in the index.html file), we can get it by copying from go’s root files.

cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .

Now we can compile or code from main.go , we compile to js runtime (GOOS) and use the wasm architecture (GARCH), and output the resault into a main.wasmfile.

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

We should now have a file named main.wasm, this is the file containing the web assembly code that we will run.

Now we can use any HTTP server to run our code, I use http-server for it, and we should see our string logged in the console.

Named functions

Now that we have a simple wasm code working, we can get started with named functions, we want to export some functions from our Go code so we can use them in our javascript code.

To bind our Go code to the JS runtime, Go provides us a package syscall/js which we can import and use to bind a function to the global window.
as you can see, our import exposes a variable named js and we can get the Global which is the window (for browsers), and we can set a function with Set, the function is called “add”, and we use the js.NewCallback to turn our Go function to javascript Function.

Ignore the lines with the done for now, they are used here to prevent the Go program from exiting (by creating a Go channel and waiting for it to receive data).

Let's implement the function named “add” in our Go code, which will accept two numbers and add them up:

// accept any number of javascript values as arguments
func add(args []js.Value) {

// convert the JS values to Integers (numbers)
var a = args[0].Int()
var b = args[1].Int()
// print the sum of the numbers
fmt.Println(a + b)
}

So our full main.go now looks like this:

Now we can call the function window.add(1,2) in our javascript code.

Passing values from Go to Javascript

That’s nice, and that’s what most tutorials will cover, but we want to get sum instead of printing it to the console.

Since js.NewCallback interface doesn’t allow us to return values, and the functions are called asynchronously, we can use good old callbacks, and later use them as promises, this is a go function we will use to call the callback, it accepts an array of js values, a value to return (“interface{}” basically means any type), and an error (if any exist).

func execCallback(args []js.Value, value interface{}, e error) {
// get the last value
var last = args[len(args) - 1]
// if the last argument is a function, invoke it
if last.Type() == js.TypeFunction {
last.Invoke(e, value)
} else {
println("no callback")
}
}

And now our main.go file will look like this:

And when we rebuild it and reload the web page, we can make a call to add like this:

add(5, 10, (sum, error) => console.log(sum));

We can turn this call into a promise to make things simpler for us, this is our new js code:

Cleaning the global scope

We are ending up with functions that are bounded to the global scope, let’s bind them to a local scope (any object) instead.

I added a function named register which we will have to call with an object, and assign it to a javascript function named __wasm_main, we will bind all other functions to this object and use them from there, meaning we are causing less pollution to the global scope.

And now to change our js code a little:

What’s next?

There are a few Webpack WASM loaders for Go, and you can use those to add Go into your frontend workflow, also there is a very interesting frontend framework that is very similar to Vue, named vugu which allows you to create wonderful UI experience using WASM and Go. If you do not know Go and wish to keep exploring it, I recommend doing the tour of go.

--

--