Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Go (wazero host SDK)

The Go binding is a host SDK over the portable aozora.wasm Extism plugin, run through the pure-Go wazero runtime. There is no cgo and no native libextism to link — go get is the whole install:

go get github.com/P4suta/aozora-go

It is one spoke of aozora’s polyglot binding strategy: rather than a hand-written native binding per language, every non-Rust front door funnels through the same aozora.wasm bytes and the same aozora::wire authority. See Choosing a binding for when to reach for Go versus the native C ABI or the in-process Rust library, and Extism plugin for the wasm artifact this SDK loads. The rationale for the whole approach is recorded in ADR-0006 (linked from the crate README).

Install & quickstart

package main

import (
	"context"
	"fmt"

	aozora "github.com/P4suta/aozora-go"
)

func main() {
	ctx := context.Background()
	p, err := aozora.Open(ctx)
	if err != nil {
		panic(err)
	}
	defer p.Close(ctx)

	html, _ := p.ToHTML("|青梅《おうめ》")
	fmt.Println(html) // <ruby>青梅<rt>おうめ</rt></ruby>

	nodes, _ := p.Nodes("|青梅《おうめ》")
	for _, n := range nodes.Data {
		fmt.Printf("%s @ [%d,%d)\n", n.Kind, n.Span.Start, n.Span.End)
	}
}

Open(ctx) instantiates the plugin once; reuse the returned Parser across calls and Close(ctx) it when done. Beyond ToHTML and Nodes, a Parser exposes Serialize, Diagnostics, Pairs, and ContainerPairs — each returning the matching wire envelope decoded into the generated Go types:

MethodReturnsNotes
ToHTML(src)stringSemantic HTML5 with aozora-* class hooks.
Serialize(src)wire envelopeCanonical 青空文庫 source round-trip.
Nodes(src)wire envelopeBorrowed-AST nodes with Kind + Span.
Diagnostics(src)wire envelopeSame diagnostic schema as every other binding (see WASM → API surface).
Pairs(src)wire envelopeMatched ruby / bracket / quote pairs.
ContainerPairs(src)wire envelopeMatched indent / align-end container pairs.

Concurrency

A Parser is not safe for concurrent use — the underlying Extism instance carries per-call wasm linear-memory state. Open one Parser per goroutine (each Open is independent), or guard a shared one behind your own mutex. For parallel corpus processing the per-goroutine pattern is the intended one; instances do not contend.

How it works

Open(ctx) loads the embedded aozora.wasm plugin into a fresh wazero runtime. Every method serialises its argument, calls the corresponding plugin export, and decodes the JSON envelope into a Go type. Those wire types live in wire_gen.go and are generated by just types-langs (quicktype, fed from the wire JSON Schema) — they are not hand-maintained, so they cannot drift from the Rust aozora::wire definitions. Because the plugin bytes and the wire schema are shared, the Go output is byte-identical to the Rust, WASM, Python, and C-ABI front doors: same HTML, same canonical serialisation, same diagnostics.

Building / contributing

From the aozora workspace root, just smoke-go builds the plugin (just extism-build), embeds the resulting aozora.wasm into the module, and runs gofmt + go vet + go test. The aozora.wasm artifact is git-ignored locally and dropped in by that target or by the release workflow; wire_gen.go is regenerated by just types-langs and must not be edited by hand.

Reference