Is a new standard binary format that allows us developers to compile programs written in high-level languages such as C, C++, Rust, and Go into low-level code that can be executed in the browser. At the moment this is something that we can only achieve using Javascript, but now, with WASM the door is open for other languages to be run on the client side.

This means that developers can use the same languages they would use to build native applications to build web applications that run in the browser, resulting in faster and more powerful web applications. This is especially useful for applications that require a lot of computing power, as they can run efficiently in the browser.

In this post, we will do a brief demo of WASM using Go, feel free to code along if you’d like.


Important ⚠️

This exercise should work just fine in Chrome or Mozilla Firefox, so please try to stick to those if you’re coding along.

We’ll start by simply writing a small web server with go, from which we’ll serve the HTML template and then wire it up to communicate with a WebAssembly module that we’ll generate to run our Go code on the client side. This is what our server’s code looks like:

Nothing fancy here, we’re just serving the files so we can see them through the browser. Now, let’s put together the program that we’ll compile for WASM. We’ll start by simply printing something out:

Now that we have the program, we’ll need to compile it to WebAssembly and wire it up to our HTML using Javascript.

To compile the program you can just simply run the following command:

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

Notice that I specified the path ./prog/main.go as the target program that will be compiled to WASM, that’s because I have both programs in the same repository, for simplicity but you can replace that with the path to the program you wish to compile to WASM.

Next, let’s move on to the UI elements. First, we’ll start by copying the Javascript support file for WebAssembly, as we’ll need it to wire up our module with the client side. We can get it by running:

cp "${go env GOROOT}/misc/wasm/wasm_exec.js"

And, this is how our JS file should look:

This bit of code will allow us to run the Go application we compiled to WASM, so as soon as we load the page we should see WASM Program Online! In the browser’s console.

Last but not least, let’s put together our HTML and call the scripts we recently added:

Now we just need to start our server by running:

go run server.go

This will start our web server and then we’ll be able to go to localhost:8080, and if you look at the console you should see the message we wrote from our Go program in there.

Now, that’s pretty cool but…

Let’s kick this up a notch

Let’s try to export a function to the client side and do some DOM manipulation while we’re at it. Let’s start by creating the callbacks we’re going to expose. We’re going to create a Go function that will tell us if there are repeated characters in the string we give it. This is how that’d look like:

And to keep things organized, I moved the core functionality of this callback to a helper function which looks like this:

Now, let’s modify our WASM program to be a long running one and register the function we just created, like so:

Lastly, we’ll tweak the JS we wrote to now call the Go program as soon as it loads the page. Now, to see the new changes in action, run the compile command again and do a hard reload on the browser. You should see the same message printed in the dev tool’s console and have the ability to call hasRepeatedChars from there as well, how neat is that!

Manipulating the DOM

Now that we’ve exported the function, let’s take it a bit further and wire that Go function with some elements in our UI.

We’ll start by tweaking the callback function to capture the Ids of the element we’ll read the input from and where we’ll show the result. Using the syscall/js will allow us to read that information and also manipulate some elements of our HTML to show the result.

Word of caution ⚠️: This is an experimental package and if you’re using VS Code like me, you might need to change two Go environment variables, GOOS=js and GOARCH=wasm to be able to import this package into your code. I had to do that to address the following error I was getting:

imports syscall/js: build constraints exclude all Go files in /usr/local/go/src/syscall/js

Now, our callbacks should look like this:

Instead of reading the values as such, we’re interpreting them as Ids to the elements we’ll use from the UI, we then capture the value provided through the input of the first argument run our logic on top of the string we received and then use the Id of the second one to update its value with the result we got. Additionally, I added a new callback, which will help us clear the inputs we get on command. This new callback relies on a small helper that looks like this:

Then we register the new callback in our program:

Now, all we need to do is to update our HTML to include two new inputs(one that we’ll use to receive the string and another one to show the result) and a couple of buttons to call the function we initially exported and the one we added to clear the inputs. This is how that should look:

Awesome! now let’s compile the program to WASM once more and hard refresh the page on the browser. You should now be able to enter a string then hit the check button and see the result printed in the disabled input next to the Clear button. Also, if we click the Clear button both inputs should be cleared.

That’s it! We have just written and compiled a Go program to WASM and ran it in the browser. This is just a simple example, but WASM allows you to do much more, such as creating interactive graphics, building games, and creating high-performance web applications.

Closing thoughts

At the moment, there have been a few production scenarios where WASM has been put to work. We have AutoCAD that was able to move its software to the web using web assembly, piggybacking off their codebase built on C++ which gave them the power to provide a desktop experience but on the web.

We also have Figma, that was able to cut down their load times by 3x and they’re currently using WASM for their web application when running on Firefox. And at eBay, they were able to back their implementation of a barcode scanner on the web by using WebAssembly as well as some JS libraries to perform the image processing.

Overall, WebAssembly is an exciting new technology that has the potential to revolutionize the way we build web applications. We’re still a long way from being able to fully rely on this technology but there’s already a community of developers putting work on this front, so it should only be a matter of time.

Further Reading