Redirects users to tested example (#791)

Rather than clutter both the README and home page with details that can
drift and have caused maintenance, this directs users to the tested
basic example.

This also adds a FAQ entry about TinyGo's main, thanks to @basvanbeek
for the help.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2022-09-01 09:12:37 +08:00
committed by GitHub
parent 1f4d945cb0
commit d54008922c
12 changed files with 124 additions and 170 deletions

View File

@@ -54,7 +54,7 @@ build.examples.as:
build.examples.zig:
@cd examples/allocation/zig/testdata/ && zig build -Drelease-small=true && mv zig-out/lib/greet.wasm .
tinygo_sources := examples/allocation/tinygo/testdata/greet.go imports/wasi_snapshot_preview1/example/testdata/tinygo/cat.go
tinygo_sources := examples/basic/testdata/add.go examples/allocation/tinygo/testdata/greet.go imports/wasi_snapshot_preview1/example/testdata/tinygo/cat.go
.PHONY: build.examples.tinygo
build.examples.tinygo: $(tinygo_sources)
@for f in $^; do \

View File

@@ -15,69 +15,9 @@ Import wazero and extend your Go application with code written in any language!
## Example
The best way to learn wazero is by trying one of our [examples](examples).
For the impatient, here's a peek of a general flow with wazero:
First, you need to compile your code into the WebAssembly Binary Format (Wasm).
Here's source in [TinyGo](https://wazero.io/languages/tinygo), which exports an
"add" function:
```go
package main
//export add
func add(x, y uint32) uint32 {
return x + y
}
```
Here's the minimal command to build a `%.wasm` binary.
```bash
tinygo build -o add.wasm -target=wasi add.go
```
Finally, you can run that inside your Go application.
```go
func main() {
// Choose the context to use for function calls.
ctx := context.Background()
// Read a WebAssembly binary containing an exported "add" function.
wasm, err := os.ReadFile("./path/to/add.wasm")
if err != nil {
log.Panicln(err)
}
// Create a new WebAssembly Runtime.
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
WithWasmCore2())
defer r.Close(ctx) // This closes everything this Runtime created.
// Instantiate WASI, which implements system I/O such as console output.
if _, err = wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
log.Panicln(err)
}
// Instantiate the module and return its exported functions
module, err := r.InstantiateModuleFromBinary(ctx, wasm)
if err != nil {
log.Panicln(err)
}
// Discover 1+2=3
fmt.Println(module.ExportedFunction("add").Call(ctx, 1, 2))
}
```
Notes:
* The embedding application is often called the "host" in WebAssembly.
* The Wasm binary is often called the "guest" in WebAssembly. Sometimes they
need [imports][imports] to implement features such as console output.
* Many languages compile to (target) Wasm including AssemblyScript, C, C++,
Rust, TinyGo and Zig!
The best way to learn wazero is by trying one of our [examples](examples). The
most [basic example](examples/basic) extends a Go application with an addition
function defined in WebAssembly.
## Deeper dive

View File

@@ -1,48 +1,62 @@
package wazero
package wazero_test
import (
"context"
_ "embed"
"fmt"
"log"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
)
// addWasm was generated by the following:
//
// cd examples/basic/testdata/testdata; wat2wasm --debug-names add.wat
// cd examples/basic/testdata; tinygo build -o add.wasm -target=wasi add.go
//
//go:embed examples/basic/testdata/add.wasm
var addWasm []byte
// This is an example of how to use WebAssembly via adding two numbers.
// This is an example of how to extend a Go application with an addition
// function defined in WebAssembly.
//
// See https://github.com/tetratelabs/wazero/tree/main/examples for more.
// Since addWasm was compiled with TinyGo's `wasi` target, we need to configure
// WASI host imports.
//
// A complete project that does the same as this is available here:
// https://github.com/tetratelabs/wazero/tree/main/examples/basic
func Example() {
// Choose the context to use for function calls.
ctx := context.Background()
// Create a new WebAssembly Runtime.
r := NewRuntime(ctx)
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
WithWasmCore2())
defer r.Close(ctx) // This closes everything this Runtime created.
// Add a module to the runtime named "wasm/math" which exports one function
// "add", implemented in WebAssembly.
// Instantiate WASI, which implements host functions needed for TinyGo to
// implement `panic`.
if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
log.Panicln(err)
}
// Instantiate the guest Wasm into the same runtime. It exports the `add`
// function, implemented in WebAssembly.
mod, err := r.InstantiateModuleFromBinary(ctx, addWasm)
if err != nil {
log.Panicln(err)
}
defer mod.Close(ctx)
// Get a function that can be reused until its module is closed:
add := mod.ExportedFunction("add")
// Call the `add` function and print the results to the console.
x, y := uint64(1), uint64(2)
results, err := add.Call(ctx, x, y)
results, err := mod.ExportedFunction("add").Call(ctx, x, y)
if err != nil {
log.Panicln(err)
}
fmt.Printf("%s: %d + %d = %d\n", mod.Name(), x, y, results[0])
fmt.Printf("%d + %d = %d\n", x, y, results[0])
// Output:
// wasm/math: 1 + 2 = 3
// 1 + 2 = 3
}

View File

@@ -1,3 +1,36 @@
## Basic example
This example shows how to use both WebAssembly and Go-defined functions with wazero.
This example shows how to extend a Go application with an addition function
defined in WebAssembly.
Ex.
```bash
$ go run add.go 7 9
7 + 9 = 16
```
### Compilation
wazero is a WebAssembly runtime, embedded in your host application. To run
WebAssembly functions, you need access to a WebAssembly Binary (Wasm),
typically a `%.wasm` file.
[add.wasm](testdata/add.wasm) was compiled from [add.go](testdata/add.go) with
[TinyGo][1], as it is the most common way to compile Go source to Wasm. Here's
the minimal command to build a `%.wasm` binary.
```bash
cd testdata; tinygo build -o add.wasm -target=wasi add.go
```
### Notes
* Many other languages compile to (target) Wasm including AssemblyScript, C,
C++, Rust, and Zig!
* The embedding application is often called the "host" in WebAssembly.
* The Wasm binary is often called the "guest" in WebAssembly. Sometimes they
need [imports](../../imports) to implement features such as console output.
TinyGo's `wasi` target, requires [WASI][2] imports.
[1]: https://wazero.io/languages/tinygo
[2]: https://wazero.io/specs/#wasi

View File

@@ -9,26 +9,40 @@ import (
"strconv"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
)
// addWasm was generated by the following:
//
// cd testdata; wat2wasm --debug-names add.wat
// cd testdata; tinygo build -o add.wasm -target=wasi add.go
//
//go:embed testdata/add.wasm
var addWasm []byte
// main implements a basic function in both Go and WebAssembly.
// main is an example of how to extend a Go application with an addition
// function defined in WebAssembly.
//
// Since addWasm was compiled with TinyGo's `wasi` target, we need to configure
// WASI host imports.
func main() {
// Choose the context to use for function calls.
ctx := context.Background()
// Create a new WebAssembly Runtime.
r := wazero.NewRuntime(ctx)
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
WithWasmCore2())
defer r.Close(ctx) // This closes everything this Runtime created.
// Add a module to the runtime named "wasm/math" which exports one function "add", implemented in WebAssembly.
wasm, err := r.InstantiateModuleFromBinary(ctx, addWasm)
// Instantiate WASI, which implements host functions needed for TinyGo to
// implement `panic`.
if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
log.Panicln(err)
}
// Instantiate the guest Wasm into the same runtime. It exports the `add`
// function, implemented in WebAssembly.
mod, err := r.InstantiateModuleFromBinary(ctx, addWasm)
if err != nil {
log.Panicln(err)
}
@@ -36,14 +50,14 @@ func main() {
// Read two args to add.
x, y := readTwoArgs()
// Call the `add` function in the module and print the results to the console.
add := wasm.ExportedFunction("add")
// Call the `add` function and print the results to the console.
add := mod.ExportedFunction("add")
results, err := add.Call(ctx, x, y)
if err != nil {
log.Panicln(err)
}
fmt.Printf("%s: %d + %d = %d\n", wasm.Name(), x, y, results[0])
fmt.Printf("%d + %d = %d\n", x, y, results[0])
}
func readTwoArgs() (uint64, uint64) {

View File

@@ -12,6 +12,6 @@ import (
// go run add.go 7 9
func Test_main(t *testing.T) {
stdout, _ := maintester.TestMain(t, main, "add", "7", "9")
require.Equal(t, `wasm/math: 7 + 9 = 16
require.Equal(t, `7 + 9 = 16
`, stdout)
}

10
examples/basic/testdata/add.go vendored Normal file
View File

@@ -0,0 +1,10 @@
package main
//export add
func add(x, y uint32) uint32 {
return x + y
}
// main is required for the `wasi` target, even if it isn't used.
// See https://wazero.io/languages/tinygo/#why-do-i-have-to-define-main
func main() {}

Binary file not shown.

View File

@@ -1,15 +0,0 @@
(module
;; Define the optional module name. '$' prefixing is a part of the text format.
$wasm/math
;; add returns $x+$y.
;;
;; Notes:
;; * The stack begins empty and anything left must match the result type.
;; * export allows api.Module to return this via ExportedFunction("add")
(func (export "add") (param $x i32) (param $y i32) (result i32)
local.get $x ;; stack: [$x]
local.get $y ;; stack: [$x, $y]
i32.add ;; stack: [$x+$y]
)
)

8
go.mod
View File

@@ -4,6 +4,8 @@ module github.com/tetratelabs/wazero
// https://go.dev/doc/devel/release (1 version behind latest)
go 1.18
// Retract the first tag, which had the wrong naming convention. Also, retract
// the first beta as it had a memory bug and quickly fixed in v1.0.0-beta.2.
retract [v1.0.0-beta1, v1.0.0-beta.1]
// Wrong naming convention
retract v1.0.0-beta1
// Has memory bug and quickly fixed in v1.0.0-beta.2.
retract v1.0.0-beta.1

View File

@@ -11,68 +11,9 @@ wazero is the only zero dependency WebAssembly runtime written in Go.
## Example
The best way to learn wazero is by trying one of our [examples][1]
For the impatient, here's a peek of a general flow with wazero:
First, you need to compile your code into the WebAssembly Binary Format (Wasm).
Here's source in [TinyGo]({{< ref "/languages/tinygo" >}}), which exports an
"add" function:
```go
package main
//export add
func add(x, y uint32) uint32 {
return x + y
}
```
Here's the minimal command to build a `%.wasm` binary.
```bash
tinygo build -o add.wasm -target=wasi add.go
```
Finally, you can run that inside your Go application.
```go
func main() {
// Choose the context to use for function calls.
ctx := context.Background()
// Read a WebAssembly binary containing an exported "add" function.
wasm, err := os.ReadFile("./path/to/add.wasm")
if err != nil {
log.Panicln(err)
}
// Create a new WebAssembly Runtime.
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
WithWasmCore2())
defer r.Close(ctx) // This closes everything this Runtime created.
// Instantiate WASI, which implements system I/O such as console output.
if _, err = wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
log.Panicln(err)
}
// Instantiate the module and return its exported functions
module, err := r.InstantiateModuleFromBinary(ctx, wasm)
if err != nil {
log.Panicln(err)
}
// Discover 1+2=3
fmt.Println(module.ExportedFunction("add").Call(ctx, 1, 2))
}
```
Notes:
* The Wasm binary is often called the "guest" in WebAssembly.
* The embedding application is often called the "host" in WebAssembly.
* Many languages compile to (target) Wasm including AssemblyScript, C, C++,
Rust, TinyGo and Zig!
The best way to learn wazero is by trying one of our [examples][1]. The
most [basic example][2] extends a Go application with an addition function
defined in WebAssembly.
## Why zero?
@@ -93,8 +34,9 @@ go get github.com/tetratelabs/wazero@main
wazero will release its first beta at the end of August 2022, and finalize
1.0 once Go 1.20 is released in Feb 2023. Meanwhile, please practice the
current APIs to ensure they work for you, and give us a [star][2] if you are
current APIs to ensure they work for you, and give us a [star][3] if you are
enjoying it so far!
[1]: https://github.com/tetratelabs/wazero/blob/main/examples
[2]: https://github.com/tetratelabs/wazero/stargazers
[2]: https://github.com/tetratelabs/wazero/blob/main/examples/basic
[3]: https://github.com/tetratelabs/wazero/stargazers

View File

@@ -33,6 +33,9 @@ package main
func add(x, y uint32) uint32 {
return x + y
}
// main is required for the `wasi` target, even if it isn't used.
func main() {}
```
The following is the minimal command to build a `%.wasm` binary.
@@ -334,6 +337,17 @@ it.
## Frequently Asked Questions
### Why do I have to define main?
If you are using TinyGo's `wasi` target, you should define at least a no-op
`func main() {}` in your source.
If you don't, instantiation of the WebAssembly will fail unless you've exported
the following from the host:
```webassembly
(func (import "env" "main.main") (param i32) (result i32))
```
### How do I use json?
TinyGo doesn't yet implement [reflection APIs][16] needed by `encoding/json`.
Meanwhile, most users resort to non-reflective parsers, such as [gjson][17].