WASI support in Go
原文在这里。
由 Johan Brandhorst-Satzkorn, Julien Fabre, Damian Gryski, Evan Phoenix, and Achille Roussel 发布于 2023年9月13日
Go 1.21添加了一个新的端口,通过新的GOOS值wasip1来定位WASI预览1系统调用API。该端口建立在Go 1.11引入的现有WebAssembly端口的基础上。
WebAssembly 是什么
WebAssembly(Wasm)是一种最初设计用于Web的二进制指令格式。它代表了一个标准,允许开发人员在Web浏览器中以接近本机速度直接运行高性能、低级别的代码。
Go首次在1.11版本中添加了对编译成Wasm的支持,通过js/wasm端口实现。这允许使用Go编译器编译的Go代码在Web浏览器中执行,但需要一个JavaScript执行环境。
随着Wasm的使用增加,除了在浏览器之外的用例也增多。许多云提供商现在提供服务,允许用户直接执行Wasm可执行文件,利用新的WebAssembly系统接口(WASI)系统调用API。
WebAssembly 系统接口
WASI定义了一个用于Wasm可执行文件的系统调用API,允许它们与系统资源进行交互,如文件系统、系统时钟、随机数据工具等等。WASI规范的最新版本被称为wasi_snapshot_preview1,从中我们派生出了GOOS名称wasip1。新版本的API正在开发中,未来在Go编译器中支持它们可能意味着添加一个新的GOOS。
WASI的创建使得许多Wasm运行时(宿主)能够围绕其标准化它们的系统调用API。一些Wasm/WASI宿主的示例包括Wasmtime、Wazero、WasmEdge、Wasmer和NodeJS。还有许多云提供商提供Wasm/WASI可执行文件的托管服务。
Go 中如何使用 WebAssembly
请确保已安装至少1.21版本的Go。对于此演示,我们将使用Wasmtime主机来执行我们的二进制文件。让我们从一个简单的 main.go 开始:
package main
import "fmt"
func main() {
fmt.Println("Hello world!")
}
使用如下命令进行编译:
$ GOOS=wasip1 GOARCH=wasm go build -o main.wasm main.go
这将会生成一个名为 main.wasm 的文件,我们可以使用 wasmtime 执行:
$ wasmtime main.wasm
Hello world!
这就是开始使用Wasm/WASI所需的全部!几乎所有Go的功能都可以在 wasip1 上正常工作。要了解有关WASI如何与Go一起工作的详细信息,请参阅提案。
测试 wasip1
构建和运行二进制文件很容易,但有时我们希望能够直接运行 go test,而无需手动构建和执行二进制文件。与 js/wasm 端口类似,Go安装中包含的标准库分发版本附带一个文件,使这个过程变得非常简单。在运行Go测试时,将 misc/wasm 目录添加到 PATH 中,它将使用你选择的Wasm主机来运行测试。这是通过 go test 在PATH中找到此文件时自动执行 misc/wasm/go_wasip1_wasm_exec 来实现的:
$ export PATH=$PATH:$(go env GOROOT)/misc/wasm
$ GOOS=wasip1 GOARCH=wasm go test ./...
这将使用 Wasmtime 运行 go test。可以使用环境变量 GOWASIRUNTIME 来控制所使用的Wasm主机。目前支持的变量值包括 wazero、wasmedge、wasmtime 和 wasmer。请注意,Go wasip1 二进制文件在所有主机上尚不能完美执行(参见#59907和#60097)。
也可以使用 go run来执行上面的程序:
$ GOOS=wasip1 GOARCH=wasm go run ./main.go
Hello world!
使用go:wasmimport在Go中包装Wasm函数
除了新的 wasip1/wasm 端口外,Go 1.21还引入了一个新的编译器指令:go:wasmimport。它指示编译器将对带有注释的函数的调用转换为对由主机模块名称和函数名称指定的函数的调用。这个新的编译器功能允许我们在Go中定义wasip1系统调用API,以支持新的端口,但它不限于在标准库中使用。
例如,wasip1系统调用API定义了 random_get 函数,并通过runtime包中定义的函数包装器暴露给Go标准库。它看起来像这样:
//go:wasmimport wasi_snapshot_preview1 random_get
//go:noescape
func random_get(buf unsafe.Pointer, bufLen size) errno
然后,将这个函数包装器包装在标准库中供使用的更人性化的函数中:
func getRandomData(r []byte) {
if random_get(unsafe.Pointer(&r[0]), size(len(r))) != 0 {
throw("random_get failed")
}
}
这样,用户可以使用字节切片调用 getRandomData ,并最终将其传递给主机定义的 random_get 函数。同样,用户可以为主机函数定义自己的包装器。
要了解如何在Go中包装Wasm函数的复杂性的更多细节,请参阅go:wasmimport提案。
局限性
虽然wasip1端口通过了所有标准库测试,但Wasm架构有一些显着的基本限制,可能会让用户感到惊讶。
Wasm是一个没有并行性的单线程架构。调度器仍然可以调度goroutine以并发运行,标准输入/输出/错误是非阻塞的,因此一个goroutine可以在另一个读取或写入时执行,但是任何主机函数调用(例如使用上面的示例请求随机数据)都会导致所有goroutine阻塞,直到主机函数调用返回。
wasip1 API中一个显着缺失的功能是完整的网络套接字实现。wasip1只定义了对已经打开的套接字进行操作的函数,这使得无法支持Go标准库的一些最流行的功能,如HTTP服务器。像Wasmer和WasmEdge这样的主机实现了wasip1 API的扩展,允许打开网络套接字。尽管Go编译器没有实现这些扩展,但存在第三方库,github.com/stealthrocket/net,使用go:wasmimport允许在支持的Wasm主机上使用net.Dial和net.Listen。这允许在使用此包时创建net/http服务器和其他与网络相关的功能。
Go中的Wasm的未来
wasip1/wasm 端口的添加只是我们希望引入Go的Wasm功能的开端。请密切关注问题跟踪器,了解有关将Go函数导出到Wasm(go:wasmexport)、32位端口和未来WASI API兼容性的提案。
参与其中
如果你正在尝试并希望为Wasm和Go做出贡献,请参与其中!Go问题跟踪器跟踪所有正在进行的工作,Gophers Slack上的 #webassembly 频道是讨论Go和WebAssembly的好地方。我们期待听到你的声音!
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
WASI support in Go的更多相关文章
- Android注解使用之使用Support Annotations注解优化代码
前言: 前面学习总结了Java注解的使用,博客地址详见Java学习之注解Annotation实现原理,从本质上了解到什么注解,以及注解怎么使用?不要看见使用注解就想到反射会影响性能之类,今天我们就来学 ...
- Android Support 包知识
Android Support Library包是一组代码库, 它提供了向后版本的framework API的兼容, 这些代码库实现的效果和只能在指定版本中使用的API一样好. 每个Support L ...
- 解决Native atomics support not found问题
今天用arm-none-linux-gnueabi交叉编译libmysqclient.so,出现Native atomics support not found问题 进入mysql-connector ...
- 使用 CoordinatorLayout 出错 inflating class android.support.design.widget.CoordinatorLayout
ava.lang.RuntimeException: Unable to start activity ComponentInfo{com.czr.ianpu/com.czr.ianpu.MainAc ...
- Your app declares support for audio in the UIBackgroundModes key in your Info.plist 错误
提交AppStore时候被拒绝 拒绝原因:Your app declares support for audio in the UIBackgroundModes key in your Info.p ...
- 在布局中使用android.support.v4.app.Fragment的注意事项
1.Activity必须继承android.support.v4.app.FragmentActivity 2.fragment标签的name属性必须是完全限定包名,如下: <LinearLay ...
- 启动项目的时候报驱动错误: not support oracle driver 1.0
问题:今天在使用pom导入oracle14的包时候发现怎么都下载不过来.网上查了一下发现是因为Oracle驱动需要官方授权,所以在pom.xml文件直接配置,无法下载成功. 解决方法就是下载oracl ...
- Android Support Library
title: Android Support Library tags: Support Library,支持库 grammar_cjkRuby: true --- DATE: 2016-5-13. ...
- How To Install Proxmox Nested on VMware ESXi (Full Support OpenVZ & KVM)
https://imanudin.net/2015/03/04/how-to-install-proxmox-nested-on-vmware-esxi-full-support-openvz-kvm ...
- CAST function should support INT synonym for SIGNED. i.e. CAST(y AS INT)
Login / Register Developer Zone Bugs Home Report a bug Statistics Advanced search Saved searches T ...
随机推荐
- wireshark分析tcp传输之文件上传速率问题
在网络性能问题排查思路那一节里,我提到了查看系统网络瓶颈的方法以及排查丢包问题的手段. 但就此分析网络问题还不够精细,有时网络资源并没有达到瓶颈,或者并没有丢包产生,但是网络传输速率就是很慢,或者有丢 ...
- [ 基于宝塔部署 ] 恋爱博客 -- Like_Girl 5.0
1)环境准备 云服务器 [ CentOS 7 ] 域名解析 love.daxiaoba.cool 宝塔面板 yum install -y wget && wget -O install ...
- Python潮流周刊#5:并发一百万个任务要用多少内存?
你好,我是猫哥.这里记录每周值得分享的 Python 及通用技术内容,部分为英文,已在小标题注明.(标题取自其中一则分享,不代表全部内容都是该主题,特此声明.) 博客原文:https://python ...
- ARC142
ARC142 考试情况:一眼订正,鉴定为做出前三题. A - Reverse and Minimize 分析题目性质可得三种情况: \(K\) 末尾有 \(0\) 最多只有 \(K\) 本身一个答案. ...
- CMU15445 (Fall 2020) 数据库系统 Project#2 - B+ Tree 详解(下篇)
前言 上一篇博客中实现了单线程 B+ 树的查找.插入.删除和迭代操作,这篇博客将完成实验二的剩余任务:并发 B+ 树.实现 B+ 树并发访问最简单的方法就是在整棵树上加一把大锁,但是这样会导致过多线程 ...
- Java并发(十一)----线程五种状态与六种状态
1.五种状态 这是从 操作系统 层面来描述的 [初始状态]仅是在语言层面创建了线程对象,还未与操作系统线程关联 [可运行状态](就绪状态)指该线程已经被创建(与操作系统线程关联),可以由 CPU 调度 ...
- 前端vue uni-app基于uQRCode封装简单快速实用全端二维码生成插件
快速实现基于uQRCode封装简单快速实用全端二维码生成插件; 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12677 效果图 ...
- PostgreSQL 12 文档: 部分 VII. 内部
部分 VII. 内部 这一部分包含PostgreSQL开发者可能用到的各类信息. 目录 50. PostgreSQL内部概述 50.1. 一个查询的路径 50.2. 连接如何建立 50.3. 分析器阶 ...
- ASL芯片CS5466方案设计|集睿致远CS5466代理商|Type-c转HDMI电路原理
CS5466作为ASL集睿致远新推出的高性能Type-C to HDMI2.1协议转换器,可以通过HDMI输出端口作为TMDS或FRL发射机进行操作. CS5466适配于多个配件市场和现实应用主板,例 ...
- 跟着 GPT-4 从0到1学习 Golang 并发机制(一)
目录 一.前言 二.开聊 2.1 Golang 里的并发机制介绍 2.2 Goroutine 与线程 2.3 Goroutine 与线程的调度开销 2.4 用户态和内核态 2.5 Golang 并发编 ...