可扩展的WASM应用程序

使用1.24增强其WebAssembly(WASM)功能 添加 go:wasmexport 指令和构建反应堆的能力 用于WebAssembly系统接口(WASI)。 这些功能使GO开发人员能够将GO函数导出到WASM, 促进与WASM主机更好地集成并扩大可能性 用于基于GO的WASM应用程序。

WebAssembly和WebAssembly系统接口

WebAssembly(WASM) 是二进制指令格式 最初是为Web浏览器创建的,提供了执行 高性能,低级代码以接近天然性能的速度。 从那以后,Wasm的实用程序已经扩展,现在在各种 浏览器以外的环境。 值得注意的是,云提供商提供直接执行WASM的服务 可执行组,利用 WebAssembly系统接口(WASI) 系统调用API。 WASI允许这些可执行文件与系统资源进行交互。

首先通过在1.11版本中添加了对WASM编译的支持, js/wasm 港口。 GO 1.21添加了一个针对WASI Preview 1 Syscall API的新端口 新的 GOOS=wasip1 港口。

与WASM一起出口GO功能 go:wasmexport

GO 1.24介绍新的编译器指令, go:wasmexport,允许 开发人员要从外部调用do go函数 WASM模块,通常来自运行WASM运行时的主机应用程序。 该指令指示编译器使带注释的功能可用 作为WASM 出口 在由此产生的WASM二进制中。

使用 go:wasmexport 指令,只需将其添加到函数定义:

//go:wasmexport add
func add(a, b int32) int32 { return a + b }

这样,WASM模块将具有名为的导出函数 add 那 可以从主机打电话。

这类似于 CGO export 指令 , 这使得该功能可从C中调用 尽管 go:wasmexport 使用不同的,更简单的机制。

构建WASI反应堆

WASI反应堆是连续运行的WebAssembly模块,并且 可以多次要求对事件或请求做出反应。 与“命令”模块不同,该模块在其主要功能完成后终止 反应堆实例在初始化后仍保持生存,其出口仍然存在 可访问。

使用GO 1.24,可以与 -buildmode=c-shared 建造 旗帜。

$ GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o reactor.wasm

链接器的构建标志信号不生成 _start 功能 (命令模块的切入点),而是生成一个 _initialize 功能,执行运行时和软件包初始化, 以及任何出口功能及其依赖性。 这 _initialize 必须在任何其他导出功能之前调用功能。 这 main 功能将不会自动调用。


要使用WASI反应器,主机应用程序首先通过调用来初始化它 _initialize,然后简单地调用导出的功能。 的示例 这是一个使用WAZERO ,该示例是基于GO的WASM运行时 执行:

// Create a Wasm runtime, set up WASI.
r := wazero.NewRuntime(ctx)
defer r.Close(ctx)
wasi_snapshot_preview1.MustInstantiate(ctx, r)
// Configure the module to initialize the reactor.
config := wazero.NewModuleConfig().WithStartFunctions("_initialize")
// Instantiate the module.
wasmModule, _ := r.InstantiateWithConfig(ctx, wasmFile, config)
// Call the exported function.
fn := wasmModule.ExportedFunction("add")
var a, b int32 = 1, 2
res, _ := fn.Call(ctx, api.EncodeI32(a), api.EncodeI32(b))
c := api.DecodeI32(res[0])
fmt.Printf("add(%d, %d) = %d\n", a, b, c)
// The instance is still alive. We can call the function again.
res, _ = fn.Call(ctx, api.EncodeI32(b), api.EncodeI32(c))
fmt.Printf("add(%d, %d) = %d\n", b, c, api.DecodeI32(res[0]))

这 go:wasmexport 指令和反应堆构建模式允许应用程序到达 通过调用基于GO的WASM代码来扩展。 这对于通过WASM作为一个的应用程序特别有价值 插件或扩展机构,具有明确的接口。 通过导出GO功能,应用程序可以利用GO WASM模块到 提供功能无需重新编译整个应用程序。 此外,作为反应堆构建可确保导出功能可以是 多次调用而无需重新定性,使其合适 用于长期运行的应用程序或服务。

支持主机和客户端之间的丰富类型

GO 1.24还放宽了可以用作输入的类型的约束和 结果参数 go:wasmimport 功能。 例如,一个人可以通过布尔,字符串,指针 int32,或 指向嵌入结构的指针 structs.HostLayout 并包含支持的 现场类型 (有关详细信息,请参见 文档 )。 这允许GO WASM应用程序以更自然和人体工程学的形式编写 方式,并删除一些不必要的类型转换。

限制

虽然GO 1.24对其WASM功能做出了重大增强,但 仍然有一些明显的限制。

WASM是一个没有并行性的单线架构。 一个 go:wasmexport 功能可以产生新的goroutines。 但是,如果一个函数创建了背景goroutine,则不会继续 执行何时 go:wasmexport 功能返回,直到回到 基于GO的WASM模块。

虽然某些类型的限制已在Go 1.24中放松,但仍有 可以使用的类型的限制 go:wasmimport 和 go:wasmexport 功能。 由于客户的64位体系结构之间的不匹配 以及主机的32位架构,不可能通过指针 记忆。 例如, go:wasmimport 函数不能将指针指向结构 包含一个指针型字段。

结论

增加构建WASI反应器并导出GO功能的能力的增加功能 WASM在GO 1.24中代表了GO的WebAssembly迈出的重要一步 功能。 这些功能使开发人员能够创建更广泛和强大的GO基础 WASM应用程序,为WASM生态系统开辟了新的可能性。 

© GVGNN 2013-2026