A complete and mature WebAssembly runtime for Go based on
Wasmer.
Features
- Easy to use: The
wasmer
API mimics the standard WebAssembly API,
- Fast:
wasmer
executes the WebAssembly modules as fast as
possible, close to native speed,
- Safe: All calls to WebAssembly will be fast, but more
importantly, completely safe and sandboxed.
Documentation: browse the detailed API
documentation
full of examples.
Examples as tutorials: browse the examples/
directory,
it's the best place for a complete introduction!
Install
To install the library, follow the classical:
$ go get github.com/wasmerio/wasmer-go/wasmer
And you're ready to get fun!
This library embeds the Wasmer runtime compiled as shared library
objects, and so uses cgo
to consume
it. A set of precompiled shared library objects are provided. Thus
this library works (and is tested) on the following platforms:
Platform |
Architecture |
Triple |
Status |
Linux |
amd64 |
x86_64-unknown-linux-gnu |
✅ |
aarch64 |
aarch64-unknown-linux-gnu |
✅ |
Darwin |
amd64 |
x86_64-apple-darwin |
✅ |
aarch64 |
aarch64-apple-darwin |
⏳ |
Windows |
amd64 |
x86_64-pc-windows-msvc |
⏳ |
What to do if your platform is missing?
Up to now, there is no script to automate that process. We are
working on it.
Here are the steps to do that manually:
$ # Build the new Wasmer C API shared object library.
$ cargo build --release
$
$ # Configure cgo.
$ export CGO_CFLAGS="-I$(pwd)/wasmer/packaged/include/"
$ export CGO_LDFLAGS="-Wl,-rpath,$(pwd)/target/release/ -L$(pwd)/target/release/ -lwasmer_go"
$
$ # Run the tests.
$ just test -tags custom_wasmer_runtime
Examples
We highly recommend to read the
examples/
directory, which contains a sequence of examples/tutorials. It's the
best place to learn by reading examples.
But for the most eager of you, there is a quick toy program in
examples/appendices/simple.go
, written in Rust:
#[no_mangle]
pub extern "C" fn sum(x: i32, y: i32) -> i32 {
x + y
}
A compiled WebAssembly binary is included in
examples/appendices/simple.wasm
.
Then, we can execute it in Go:
package main
import (
"fmt"
"io/ioutil"
wasmer "github.com/wasmerio/wasmer-go/wasmer"
)
func main() {
wasmBytes, _ := ioutil.ReadFile("simple.wasm")
engine := wasmer.NewEngine()
store := wasmer.NewStore(engine)
// Compiles the module
module, _ := wasmer.NewModule(store, wasmBytes)
// Instantiates the module
importObject := wasmer.NewImportObject()
instance, _ := wasmer.NewInstance(module, importObject)
// Gets the `sum` exported function from the WebAssembly instance.
sum, _ := instance.Exports.GetFunction("sum")
// Calls that exported function with Go standard values. The WebAssembly
// types are inferred and values are casted automatically.
result, _ := sum(5, 37)
fmt.Println(result) // 42!
}
And then, finally, enjoy by running:
$ cd examples/appendices/
$ go run simple.go
42
Testing
Run the tests with the following command:
$ just test
What is WebAssembly?
Quoting the WebAssembly site:
WebAssembly (abbreviated Wasm) is a binary instruction format for a
stack-based virtual machine. Wasm is designed as a portable target
for compilation of high-level languages like C/C++/Rust, enabling
deployment on the web for client and server applications.
About speed:
WebAssembly aims to execute at native speed by taking advantage of
common hardware
capabilities
available on a wide range of platforms.
About safety:
WebAssembly describes a memory-safe, sandboxed execution
environment […].
License
The entire project is under the MIT License. Please read the
LICENSE
file.
FAQ
How to run Go programs compiled to WebAssembly modules with wasmer-go
?
Let's start by emphasing that wasmer-go
is a WebAssembly runtime. It
allows to run WebAssembly inside Go. It's not a tool to compile a
Go program into WebAssembly. Nonetheless, many people are reporting
issues when compiling Go programs to WebAssembly, and then trying to
run them with wasmer-go
(or in another hosts, like
Python,
C,
PHP,
Ruby,
Rust…).
The major problem is that, whilst the Go compiler supports
WebAssembly, it does not support
WASI (WebAssembly System
Interface). It generates an ABI that is deeply tied to JavaScript, and
one needs to use the wasm_exec.js
file provided by the Go toolchain,
which doesn't work outside a JavaScript host.
Fortunately, there are two solutions to this problem:
-
Use TinyGo to compile your Go program to
WebAssembly with the -target wasi
option, e.g.:
$ tinygo build -o module.wasm -target wasi .
The generated WebAssembly module will be portable across all
WebAssembly runtimes that support WASI.
-
Use the Go compiler with adapters. Let's see how to compile:
$ GOOS=js GOARCH=wasm go build -o module.wasm .
(the GOOS=js
is the sign that JavaScript is targeted, not a surprise).
Then pick one adapter (they are written by the community):
and follow their documentation.
We highly recommend the first solution (with TinyGo) if it works for
you as the WebAssembly module will be portable across all WebAssembly
runtimes. It's not a hacky solution based on adapters; it's the right
way to… go.