WebAssembly 简介

冰岩作坊 November 24, 2023

大家好啊,今天我来介绍一种很新的技术:WebAssembly(wasm),并简单尝试使用 Golang 写点 wasm 有意思的小东西。

Wasm 是什么

WebAssembly(缩写为 Wasm)是一种基于堆栈的虚拟机的二进制指令格式。Wasm 被设计为编程语言的可移植编译目标,可以在浏览器或其他提供了 wasm 支持的环境中运行。

有什么用呢

Wasm 目前已经在浏览器端的图像处理、音视频处理、游戏、IDE、可视化、科学计算等,以及非浏览器端的Serverless、区块链、IoT 等领域有一定的应用,一些现实中的应用例子有:

甚至,还能和之前说的 ebpf 结合,太神奇啦:eunomia-bpf/wasm-bpf: WebAssembly library, toolchain and runtime for eBPF programs (github.com)##

运行时架构

* 模块加载和解析器:负责将 WebAssembly 二进制文件加载到内存中,按照规范定义的属性文法进行解码,验证和实例化,生成 WebAssembly 模块对象和运行时数据区域。

垃圾回收

对 WebAssembly 而言,初期的主要设计目标是提供一个底层的高效二进制格式及其对应的运行环境,并将静态强类型语言直接静态编译到字节码,避免在语言层面的额外开销,从而提升性能。因此,WebAssembly 没有垃圾收集器,它只提供了一块可以按字节寻址的线性内存。对于基础数据类型,wasm 可以在内存中高效地访问和传递,而对于结构体、数组等复杂的数据结构,需要手动负责对象创建和回收对象或者采用优化的内存分配器来完成内存的管理工作。目前,对这方面的讨论还在激烈进行中,不支持 GC 的人认为没必要,而支持 GC 的人认为:* 采用垃圾收集器,WebAssembly 可以以更快的执行性能,更小的体积支持更广泛的现代高级语言。

在 Golang 中写 wasm,首先我们需要一个编译的工具:TinyGo(事实上 Go 自己也能直接编译 wasm,但是目前的支持似乎还不太好),其次,要在本地运行 wasm,我们还需要一个运行环境:Wasmer: Run, Publish & Deploy any code, anywhere安装完成后就可以开始试试下面的代码啦!### Hello world

1
2
3
4
5
6
7
* 
*
*
*
*
*
// main.gopackage mainfunc main()

编译:```

*
tinygo build -o main.wasm -target=wasm main.go

1
运行:* 

wasmer run main.wasm

1
2
```

###

不写 js 也能写前端

还是上面这段代码,我们可以通过一些方法让它在浏览器里运行:创建一个 index.html:```

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*
Go wasm

1
2
3
把需要的文件复制过来```
*
cp "$(tinygo env TINYGOROOT)/targets/wasm_exec.js" ./wasm_exec.js

在浏览器里打开,就能看到程序输出的结果啦另外 Go 内置的 syscall/js 提供了一些方法来调用 js 函数,我们可以用它实现一些操作,比如:```

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*

*
package mainimport ( “syscall/js” “time”)func GenshinImpact() js.Global().Get(“location”).Call(“replace”, “https://ys.mihoyo.com/")}func main() }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
![](https://mmbiz.qpic.cn/mmbiz_gif/rxLIic6e5g8S48GpJrBu3D0icydcQLOVNeKMnB5qvNEbSEibaxYZb6pPQ9jM3wPwEt0SFbtUEHiatLoR07PndemJTw/640?wx_fmt=gif&from=appmsg)另外还有把不写 js 贯彻到底的项目:Vugu: A modern UI library for Go+WebAssembly,虽然看起来已经很久没更新了...### 插件系统

参考 wasmerio/wasmer-go: WebAssembly runtime for Go 里的例子:```
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
package mainimport ( "fmt" wasmer "github.com/wasmerio/wasmer-go/wasmer" "os")func main()

这下我们可以动态加载各种 wasm 模块了,而且插件不限制编写语言,可以在各种平台上运行,比 Go 自带的 plugin 好太多啦!##

总结

总的来说,WebAssembly 作为一种新兴的技术,具有广泛的应用前景,并且在不断演进和完善中,期待它未来的发展!## 参考文章

#走进 WebAssembly 的世界 (qq.com)