Unleashing the Power of WebAssembly System Interface (WASI) in Go

Rajiv Ranjan Singh

A.P. Moller - Maersk

India 🇮🇳

WasmCon 2023

Rajiv Ranjan Singh

Software Engineer @ A.P. Moller - Maersk
I graduated in August, 2022 from JSSATE Bengaluru, India

Agenda

Prerequisites: WebAssembly

  • What is WebAssembly?

  • The WebAssembly System Interface

  • Overview of Go's Existing WebAssembly Support

  • WASI Support in the Go Toolchain

  • Demonstration

  • The future of Wasm in Go

What is WebAssembly?

 

WebAssembly (Wasm) is a binary instruction format originally designed for the web. It represents a standard that allows developers to run high-performance, low-level code directly in web browsers at near-native speeds.
 

Go first added support for compiling to Wasm in the 1.11 release through the js/wasm port. This enabled Go code compiled using the Go compiler to be executed in web browsers, albeit requiring a JavaScript execution environment.
 

As the use of Wasm has grown, so have the use cases outside of the browser. Many cloud providers are now offering services that enable users to execute Wasm executables directly, leveraging the new WebAssembly System Interface (WASI) syscall API.

The WebAssembly System Interface

WASI defines a system for WebAssembly (Wasm) programs to communicate with computer resources like the filesystem, system clock, and random data utilities. The most recent WASI specification is known as wasi_snapshot_preview1, leading to the GOOS name wasip1. Future versions of the API are in development, and incorporating them into the Go compiler might mean introducing a new GOOS.
 

The establishment of WASI has enabled various Wasm runtimes (hosts) to standardize their communication with the system through this API. Examples of Wasm/WASI hosts encompass Wasmtime, Wazero, WasmEdge, Wasmer,  NodeJS. Additionally, several cloud providers offer hosting for Wasm/WASI executables.

WASI Support in the Go Toolchain

Go 1.21 adds a new port targeting the WASI preview 1 syscall API through the new GOOS value wasip1. This port builds on the existing WebAssembly port introduced in Go 1.11.

Along with the new wasip1/wasm port, Go 1.21 also brings a new compiler instruction called go:wasmimport. This instruction tells the compiler to change calls to a specific function into calls to another function specified by the host module and function name. This new feature in the compiler helped us create the wasip1 syscall API in Go for the new port, but it can be used for more than just the standard library.

  • Limitation: wasip1 API lacks comprehensive network socket functionality, hindering support for key features like HTTP servers from the Go standard library.
  • Solution: Third-party library github.com/stealthrocket/net, utilizing go:wasmimport, enables net.Dial and net.Listen on compatible Wasm hosts, facilitating the creation of net/http servers and other network-related functionalities.

Make sure that you have installed at least version 1.21 of Go. For this demo, we’ll use the Wasmtime host to execute our binary.
package main

import "fmt"

func main() {
    fmt.Println("Hello wasip1!")
}

We can build it for wasip1 using the command:
$ GOOS=wasip1 GOARCH=wasm go build -o main.wasm main.go

This will produce a file, main.wasm which we can execute with wasmtime:
$ wasmtime main.wasm
Hello wasip1!

Demonstration

The future of Wasm in Go

  • Docker & Kubernetes
    Potential future support for WASI modules opens doors for serverless and edge deployments.
  • wasip2 Development
    Standardization brings stability and wider adoption. - go:wasmexport: Seamless integration of Go functions with Wasm expands capabilities.
  • GOARCH=wasm32
    Expands target platform, enabling Wasm on more architectures.

 

Overall, these advancements position Go to play a significant role in the future of the Wasm ecosystem.

Thank You, 🙏 🎉