WebAssembly & TinyGo Basics
10 examples to get you started with WASM & TinyGo - 7 basic and 3 intermediate.
Search across all documentation pages
10 examples to get you started with WASM & TinyGo - 7 basic and 3 intermediate.
brew install wasmtime (macOS) or download from wasmtime.dev.tinygo version.mkdir wasmdemo && cd wasmdemo && go mod init example.com/wasmdemo.The smallest proof that Go emits a runnable .wasm module.
package main
import "fmt"
func main() {
fmt.Println("hello from wasip1/wasm")
}GOOS=wasip1 GOARCH=wasm go build -o hello.wasm .
wasmtime run hello.wasmGOOS=wasip1 selects WASI Preview 1 imports instead of Linux syscalls.hello.wasm artifact - no separate Go binary.wasmtime run provides the WASI host imports the module expects.Related: Compiling with GOOS=wasip1 GOARCH=wasm - flags and linker options
Shrink download size with standard linker flags.
GOOS=wasip1 GOARCH=wasm go build -ldflags="-s -w" -o hello.wasm .-s omits the symbol table; -w omits DWARF debug info.Related: WASM Size Optimization: TinyGo vs gc WASM - deeper size tactics
WASI exposes os.Getenv through host imports.
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("USER=", os.Getenv("USER"))
}wasmtime run --env USER=ada hello-env.wasm--env flags in wasmtime for reproducible tests.Filesystem access requires the host to pre-open directories.
GOOS=wasip1 GOARCH=wasm go build -o write.wasm .
mkdir -p /tmp/wasmout
wasmtime run --dir /tmp/wasmout::/data write.wasmos.WriteFile("/data/out.txt", []byte("ok"), 0o644)--dir host::guest syntax.FSConfig directory mounts.TinyGo emits far smaller modules when its stdlib subset suffices.
package main
import "fmt"
func main() {
fmt.Println("hello from tinygo wasm")
}tinygo build -target=wasm -o tinyhello.wasm .
wasmtime run tinyhello.wasm-target=wasm selects the generic WASM backend (verify board-specific targets separately).Related: TinyGo for Microcontrollers & Constrained WASM - board targets
Isolate browser-only entrypoints from WASI builds.
//go:build js && wasm
package main
import "syscall/js"
func main() {
js.Global().Get("console").Call("log", "hello browser")
select {}
}GOOS=js GOARCH=wasm go build -o main.wasm .select {} keeps main alive so callbacks can fire.wasm_exec.js from $(go env GOROOT)/misc/wasm/wasm_exec.js in HTML hosts.syscall/js in wasip1 packages.Related: syscall/js: Go in the Browser - DOM callbacks
Inspect the module surface before embedding.
wasm-tools print hello.wasm | head_start, memory export, and WASI import names.wasm-tools via cargo install wasm-tools or your package manager.Run a guest module from a Go service without cgo.
package main
import (
"context"
"os"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
)
func main() {
ctx := context.Background()
r := wazero.NewRuntime(ctx)
defer r.Close(ctx)
wasi_snapshot_preview1.MustInstantiate(ctx, r)
wasmBytes, _ := os.ReadFile("hello.wasm")
mod, _ := r.Instantiate(ctx, wasmBytes)
defer mod.Close(ctx)
start := mod.ExportedFunction("_start")
_, _ = start.Call(ctx)
}wasi_snapshot_preview1 registers WASI imports the Go module needs.Instantiate compiles and loads bytecode; reuse Runtime across requests in servers.context deadlines to bound guest execution time.Related: WASI Host Runtimes: wasmtime, wazero & Spin - runtime comparison
Catch broken builds before deploy.
GOOS=wasip1 GOARCH=wasm go build -o /tmp/app.wasm ./...
wasmtime run /tmp/app.wasmGOOS=linux GOARCH=amd64 compile checks.wasmtime run exit codes.wasmtime and tinygo versions in CI images for reproducibility.Related: WebAssembly & TinyGo Best Practices - CI and import hygiene
Make data-driven toolchain choices.
GOOS=wasip1 GOARCH=wasm go build -ldflags="-s -w" -o gc.wasm .
tinygo build -target=wasm -o tiny.wasm .
ls -lh gc.wasm tiny.wasmRelated: Native Go vs TinyGo vs Rust WASM Decision Guide - ranked trade-offs
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 18, 2026