How To: Compile a WebAssembly Module From Go
This publication is meant to serve as a very basic set of instructions for compiling a WebAssembly module from Go. More specifically, I will demonstrate how to use the compiled WebAssembly module on a web page served by a Go web server.
Prerequisites
Tutorial Project Setup
First, let’s create a new directory for our project called wasm-go
and cd
into it:
mkdir wasm-go && cd wasm-go/
Now from the newly created wasm-go/
directory, let’s create a new file named webserver.go
and add the following code:
package main
import (
"html/template"
"log"
"net/http"
)
func main() {
tmpl, err := template.ParseFiles("templates/index.tmpl")
if err != nil {
log.Fatal(err)
}
fs := http.FileServer(http.Dir("public/"))
http.Handle("/public/", http.StripPrefix("/public/", fs))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if err := tmpl.Execute(w, nil); err != nil {
log.Fatal(err)
}
})
if err := http.ListenAndServe(":9990", nil); err != nil {
log.Fatal(err)
}
}
The above code that you just added to your webserver.go
file, provisions a web server, listens to requests on port 9990, serves public files from the URI: /public
, and serves an index page from the URI: /
.
Next, let’s create our index page. From the root wasm-go/
directory, create a new directory called templates/
and within that directory create a file called index.tmpl
and add the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello, WebAssembly!</title>
</head>
<body>
<script src="public/app.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("public/app.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</body>
</html>
The above code that you just added to your templates/index.tmpl
file, references our compiled WebAssembly module using JavaScript. 2 files are created when you compile a WebAssembly module, which we are using in the JavaScript code above: app.js
, and app.wasm
. Let’s keep going to take a closer look.
Now back at our project root, let’s create a new directory called public/
. This directory is going to contain our compiled WebAssembly code which we will publicly reference on our web page, as you saw in the above code snippet.
mkdir public
Moving on, create a new directory called app/
. This directory is going to contain our Go module that we will be compiling to WebAssembly.
So let’s cd
into our newly created app/
directory and initialize an arbitrary Go module called wasm-go
by running the following command:
go mod init wasm-go
The above command initializes a new Go module in your wasm-go/app/
directory by automatically generating a go.mod
file.
Finally, let’s write our arbitrary Go program that we want compiled to WebAssembly. So let’s create a new file called main.go
in the project’s app/
directory and add the following code:
package main
import "fmt"
func main() {
fmt.Println("Hello, WebAssembly!")
}
Great! Your project tree so far should look like this:
wasm-go/
├─ app/
│ ├─ go.mod
│ └─ main.go
├─ public/
├─ templates/
│ └─ index.tmpl
└─ webserver.go
Compiling to WebAssembly
To compile the project’s Go module to WebAssembly, run the following command from the root of the project:
cd app/ && GOOS=js GOARCH=wasm go build -o ../public/app.wasm
The above command goes into the directory where our Go module lives, app/
, compiles the Go module to WebAssembly, and generates a compiled WebAssembly file called app.wasm
in our project’s public/
directory.
Since the above command also generates a JavaScript WebAssembly support file, we need to be sure to copy that file to our project’s public/
directory as well. Let’s do so by running the following command:
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" ../public/app.js
Running the Project’s Web Server
To run the project’s Go web server, run the following command:
go run webserver.go
Navigate to http://localhost:9990/, open the JavaScript debug console, and you should see the output from our Go module: “Hello, WebAssembly!”. You can modify the program, rebuild app.wasm
, and refresh to see new output.
Voila! There you have it, your first WebAssembly module from Go.
Conclusion
This tutorial is meant to be a very basic foundation to what’s possible with WebAssembly and Go. I hope you found this to be informative. The full codebase for this tutorial can be found here. Have a great day!