Go1.17.2 发布暨 WebAssembly 入门教程
争做团队核心程序员,关注「幽鬼」
凌晨,Go 官方发布了 Go1.17.2 和 1.16.9,这是两个小版本,重要修复一个安全问题。
从使用 GOARCH=wasm GOOS=js
构建的 WASM 模块调用函数时,传递非常大的参数可能会导致模块的一部分被参数中的数据覆盖。如果使用 wasmexec.js 执行 WASM 模块,则用户需要在重新构建任何模块后替换其副本。具体 issue 见:https://github.com/golang/go/issues/48797。
我想,目前应该很少有人使用 Go 开发 WASM 吧,更多是在试验、学习。
借此,来一份简单的 Go WebAssembly 教程。
Go 1.11 added an experimental port to WebAssembly. Go 1.12 has improved some parts of it, with further improvements expected in Go 1.13.
WebAssembly is described on its home page as:
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
If you’re new to WebAssembly read the Getting Started section, watch some of the Go WebAssembly talks, then take a look at the Further examples below.
简介
什么是 WebAssembly?在其主页上:https://webassembly.org/ 有如下描述:
WebAssembly(缩写为 Wasm)是一种用于基于堆栈的虚拟机的二进制指令格式。Wasm 被设计为用于编译编程语言的可移植目标,支持在 Web 上部署客户端和服务器应用程序。
目前 Rust 对 WebAssembly 的支持较好。那 Go 什么时候开始支持支持 WebAssembly 的呢?
Go 1.11 向 WebAssembly 添加了一个实验性端口。Go 1.12 对其某些部分进行了改进,Go 1.13 有了进一步改进。
入门示例
首先,请保证安装了 Go1.11 以上版本,建议安装最新版本 Go。
在本地创建一个项目:gowasm(Windows 用户自行修改路径)
$ mkdir ~/gowasm
$ cd ~/gowasm
$ go mod init gowasm
$ touch main.go
要为 Web 编译基本的 Go 包,打开 main.go,填上如下代码:
package main
import "fmt"
func main() {
fmt.Println("Hello, WebAssembly!")
}
为 WebAssembly 编译设置GOOS=js
和GOARCH=wasm
环境变量:
$ GOOS=js GOARCH=wasm go build -o main.wasm
这将构建包并生成一个名为 main.wasm 的可执行 WebAssembly 模块文件。.wasm
文件扩展名使得通过 HTTP 用正确的 Content-Type 标头来更好地提供它。
请注意,你只能编译 main 包。否则,你将获得一个无法在 WebAssembly 中运行的目标文件。如果你有一个包希望能够与 WebAssembly 一起使用,请将其转换为 main 包并构建它得到一个二进制文件。
要在浏览器中执行 main.wasm,我们还需要一个 JavaScript 支持文件和一个 HTML 页面来将所有内容连接在一起。
复制 JavaScript 支持文件:
$ cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
创建一个index.html
文件:
<html>
<head>
<meta charset="utf-8"/>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body></body>
</html>
如果你的浏览器尚不支持WebAssembly.instantiateStreaming
,可以使用 polyfill。
然后从 Web 服务器服务这三个文件(index.html
、wasm_exec.js
和 main.wasm
)。例如,使用 goexec。注意,安装 goexec 后,放入 PATH 目录,方便使用:
# 先安装 goexec
$ go install github.com/shurcooL/goexec@latest
# 执行 goexec(如果提示你缺少 github.com/shurcooL/go-goon,请 go get 下载)
$ goexec 'http.ListenAndServe(`:8080`, http.FileServer(http.Dir(`.`)))'
当然也可以使用任何其他的方式提供 HTTP 服务。
打开浏览器访问 http://localhost:8080/index.html
,打开 JavaScript 调试控制台(Console Tab),你应该会看到输出:Hello, WebAssembly!
你可以修改程序、重新编译 main.wasm
,刷新以查看新输出。(goexec 不需要重启)
总结
Go 的安全更新,如果涉及到你的项目,建议升级,否则可以不升级。WebAssembly 这两年挺火的,但生产使用还是很少。有兴趣可以学习了解。本文希望能够带给你一个初步印象。
往期推荐
欢迎关注「幽鬼」,像她一样做团队的核心。