WebAssembly, also known as Wasm, is a way to compile code written in one programming language, such as C or Rust, and run it on a different runtime, such as in a web browser or microservice. This makes it a great choice for writing plug-ins, extensions and, in general, running user-defined arbitrary code in a safe, sandboxed environment.
WebAssembly is often mistaken for a technology that is only used in the browser when, really, Wasm is a cross-platform binary that can be executed by any WebAssembly runtime. Historically, there were not many good options for Go programmers, but this has changed.
This post introduces wazero, why it matters for infrastructure written in the Go programming language, and covers its most compelling features.
A short history of running WebAssembly in Go
In the beginning, most WebAssembly runtimes were written in the C/C++ and Rust programming languages. Many cloud native projects, including Docker, Istio, and Kubernetes are written in Go. Runtimes not written in Go could be used through a mechanism called CGO. However, CGO is not Go: by opting into CGO, you give up many of the killer features of the Go runtime, such as first-class support for cross-compilation targeting a wide array of platforms. For example, complications around CGO, specifically the implied native libraries, was why a request to extend the Kubernetes scheduler with wasm was denied. In summary, the lack of a native runtime for Go delayed or limited introduction of WebAssembly into core infrastructure.
wazero was written for Go developers
wazero is the only zero-dependency WebAssembly runtime written in Go. This open source project began as a hobby of Takeshi Yoneda. In late 2021, Tetrate recognized its strategic value and sponsored multiple full-time staff towards, one day, a 1.0 release.
In the last months, the team has worked tirelessly to harden support of multiple platforms, architectures and programming interfaces. We are thrilled to announce wazero 1.0 is releasing next week!
wazero is a fully-functional, standards-compliant, rich, and battle-tested WebAssembly runtime that integrates seamlessly with the best features of the Go runtime, such as safe concurrency and context propagation. It includes both programming interfaces for Go developers and a CLI for those who wish to just run Wasm.
What’s different about wazero?
You may wonder what is compelling about wazero, considering Go has good interoperability with other languages. This allows you to choose between several runtimes not written in Go, via CGO. Here are five reasons to consider wazero:
- Best-in-class Go support. Wazero is pure Go, and doesn’t introduce any dependencies, but support goes farther than that. Wazero includes idiomatic Go features, such as context integration. This allows you to re-use incoming deadlines, such as from a gRPC request to limit time spent in wasm functions. The runtime was designed specifically for Go, so it is well documented especially around concerns for Go developers such as goroutine safety. For example, many libraries can use wazero at the same time without conflicts with each-other, and these are tested in Go.
- API compatibility. A WebAssembly runtime is embedded at a low level in projects, so changes in compatibility can cause version locks, especially in middleware. Wazero is unique in known runtimes as it provides semantic versioning. Features can be made to 1.1 and they won’t break users of 1.0. Wazero promises to remain zero dependencies and also work with two prior versions of Go. In summary, wazero’s compatibility approach was modeled after Go itself, to introduce least maintenance problems for its users.
- Platform compatibility. wazero has full support for any combination of amd64, arm64, FreeBSD, Linux, macOS, and Windows on the most recent three versions of Go. It also extends support for other platforms Go supports through its “interpreter runtime,” which executes slower than the native “compiler runtime.” wazero is uniquely good at Windows, as not only is that platform top tier, but we also produce signed MSI installers on release.
- Rock-solid test approach. Wazero tests platform support through multiple specification tests including 1.0 and 2.0 draft versions of WebAssembly Core Specification, and the WASI test suite used to test I/O functionality. We also run standard library tests written by Zig and TinyGo. Finally, we run benchmarks and “fuzz testing” on every change. All of these combine to make wazero bugs easy to identify and fix.
- Vibrant community of contributing end users. wazero’s community includes extremely strong developers at many companies. We are involved in a lot of aspects around Go support of WebAssembly in general and contribute both to the Go and TinyGo compilers. Please check out our community and users page to learn more about us and how you fit in!
Embedding wazero in your project
Wazero is obviously also a Go library with the primary objective of allowing you to seamlessly integrate with the runtime environment and extend your Go applications with WebAssembly. For let’s say you want to run the classic Unix program cowsay (originally written in Perl). Then you may type:
// Download the executable from:
// https://github.com/evacchi/cowsay/releases/download/0.1.0/cowsay.wasm
//go:embed "cowsay.wasm"
var cowsay []byte
func main() {
ctx := context.Background()
r := wazero.NewRuntime(ctx)
wasi_snapshot_preview1.MustInstantiate(ctx, r)
r.InstantiateWithConfig(ctx, cowsay,
wazero.NewModuleConfig().
WithArgs("cowsay", // first arg is usually the executable name
"wazero is awesome!").
WithStdout(os.Stdout))
}
When run, this will display:
____________________
< wazero is awesome! >
--------------------
^__^
(oo)_______
(__) )/
||----w |
|| ||
Getting started with the wazero CLI
The project now includes a CLI to run WebAssembly binaries. We have found that many users are picking it regardless of their choice of programming language, so we decided to acknowledge their use case, by making it even more convenient to try.
You can now download and install the wazero CLI with a simple command:
$ curl https://wazero.io/install.sh | sh
Or, on Windows, you can download a signed MSI
And then you can run your WebAssembly binary with
$ ./bin/wazero run someApp.wasm
For instance, let’s say you want to run cowsay at the CLI, then you may just type
$ curl -LO https://github.com/evacchi/cowsay/releases/download/0.1.0/cowsay.wasm
$ wazero run cowsay.wasm wazero is awesome!
____________________
< wazero is awesome! >
--------------------
^__^
(oo)_______
(__) )/
||----w |
|| ||
Or, maybe you would rather play the 1977 Infocom text adventure Zork.
You can fetch a Wasm binary of it from https://github.com/evacchi/zork-1/releases/tag/v0.0.1 and then invoke it with the command:
$ curl -L https://github.com/evacchi/zork-1/releases/download/v0.0.1/zork-wasm-wasi.tgz | tar xzf -
$ wazero run -mount=.:/ zork.wasm
Welcome to Dungeon. This version created 11-MAR-91.
You are in an open field west of a big white house with a boarded
front door.
There is a small mailbox here.
>open mailbox
Opening the mailbox reveals:
A leaflet.
>read leaflet
Taken.
Welcome to Dungeon!
Dungeon is a game of adventure, danger, and low cunning. In it
you will explore some of the most amazing territory ever seen by mortal
man. Hardened adventurers have run screaming from the terrors contained
within.
In Dungeon, the intrepid explorer delves into the forgotten secrets
of a lost labyrinth deep in the bowels of the earth, searching for
vast treasures long hidden from prying eyes, treasures guarded by
fearsome monsters and diabolical traps!
No DECsystem should be without one!
Have fun!
Final remarks
This is our first major release, but we are just getting started! There are many things to look forward to.
The WebAssembly spec is constantly being updated, and we will follow it closely: for instance, the tail call proposal has just moved to Phase 4, and the GC proposal, an enabler for a number of programming languages such as Java, has recently moved to Phase 3. Wazero will continue to pass all tests as WebAssembly evolves.
We also want to remain strategic to you as a runtime choice. You can expect continued dedication to performance, observability and extensibility. One example is our upcoming low-level file-system plugin. This supports more features than Go’s fs.FS, which you can use today, such as creating directories and files. The design supports custom auditing and access control, as well as use in third party host functions.
Finally, if you happen to be in Barcelona for Wasm I/O on March 23 and 24, get a chance to get to know part of the team!
And if you are sticking around after the end of the conference, or you simply are in the city that night, on Friday March 24, we are also happy to invite you to wazero 1.0’s very own official release party! We will bring snacks, drinks and a number of community contributors that will show off what they do with our beloved WebAssembly runtime! One lucky attendee will get to press the release button on 1.0!
We are excited to see what you will build with Wazero. Join our growing list of community users and let us know what you are creating!