使用Golang编译WebAssembly

WebAssembly 在前端的应用中得到了广泛的实践,来讲下使用 Golang 编译成 WebAssembly 的方法。

首先准备一份需要编译成 WebAssembly 的 Go 文件,例如:

1
2
3
4
5
6
package main
import "fmt"
var a = 4
func main() {
fmt.Println(a)
}

在该文件的目录下直接使用 Go 自带的命令, 将 GO 文件编译成 wasm 。

1
GOOS=js GOARCH=wasm go build -o filename.wasm

然后在目录下可以看到一份以 .wasm 结尾的文件,这份文件就是编译出来我们需要在前端引入的 WebAssembly,因为 WebAssembly 与 JS 的通讯需要引入一个 50k-100k 的 JavaScript 类库作为基础设施,Go 本身提供了这个库。

1
cp "$GOROOT/misc/wasm/wasm_exec.js" /yourpath

然后就可以新建一份 html 文件来引入刚编译的 wasm 文件了,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<head>
<meta charset="utf-8">
<script src="./wasm_exec.js"></script>
<script>
const go = new Go()
WebAssembly.instantiateStreaming(fetch("filename.wasm"), go.importObject).
then((result) => {
go.run(result.instance)
})
</script>
</head>
<body></body>
</html>

当然如果你像我一样使用的是python 自带的 http server 服务的话还需要配置一下让 静态资源支持 wasm文件

1
sudo vim /usr/local/etc/mime.types

然后添加

1
application/wasm    wasm

这样在 Chrome 中就不会出现报错了,便能愉快的访问自己本地搭建的测试 wasm 的地址了。

最后作为一个 Go 吹,还是要指出 由于Go是一种垃圾收集语言,因此整个运行时都在wasm二进制文件中。因此,二进制文件通常有几MB的大小

比如像这个简单的几行 Go 代码编译出来的 wasm 文件就有 2.4M 大小。

相对于 C/C++ 这无疑是个巨大的缺点,另外 C/C++可以通过 Emscripten 编译成浏览器支持更广泛的 asm.js 。

希望以后 Golang 能对 wasm 的支持更棒吧。

hi you can see me