Golang中Wasm与Go 1.16+版本的兼容性问题探讨
Golang中Wasm与Go 1.16+版本的兼容性问题探讨 大家好, 我在尝试使用 Go 1.16 运行一个 Wasm 示例时遇到了一些问题。下面的代码在 Go 1.13 中可以工作,但在 Go 1.16 中不行(在 Ubuntu 系统上使用 Chrome 89)。
Go 文件:
import "syscall/js"
func main() {
doc := js.Global().Get("document")
doc.Call("getElementById", "hello").Set("innerHTML", "Hello Wasm!")
}
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>
<h2>WebAssembly content</h2>
<div id="hello"></div>
</body>
</html>
执行环境:
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
GOOS=js GOARCH=wasm go build -o main.wasm
python3 -m http.server
浏览器控制台错误日志:
Uncaught (in promise) LinkError: WebAssembly.instantiate(): Import #1 module=“go” function=“runtime.resetMemoryDataView” error: function import requires a callable Promise.then (async) (anonymous) @ (index):7
非常感谢任何建议。 谢谢,
更多关于Golang中Wasm与Go 1.16+版本的兼容性问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang中Wasm与Go 1.16+版本的兼容性问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个典型的 Go 1.16+ 版本中 WebAssembly 运行时兼容性问题。问题出在 wasm_exec.js 文件版本不匹配。
问题分析
Go 1.16 对 WebAssembly 运行时进行了重大更新,需要匹配版本的 wasm_exec.js 文件。你复制的 wasm_exec.js 可能来自旧版本的 Go 安装,或者编译时使用的 Go 版本与运行时提供的 JavaScript 文件版本不一致。
解决方案
1. 确保使用正确版本的 wasm_exec.js
使用与 Go 编译器相同版本的 wasm_exec.js:
# 清除旧的 wasm_exec.js
rm wasm_exec.js
# 从当前 Go 安装复制正确的版本
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
2. 更新构建命令
确保使用正确的构建标签和参数:
# 清理之前的构建
rm -f main.wasm
# 使用 Go 1.16+ 的构建命令
GOOS=js GOARCH=wasm go build -o main.wasm
3. 修改 HTML 文件中的加载方式
更新 HTML 中的 WebAssembly 加载代码,添加错误处理:
<html>
<head>
<meta charset="utf-8"/>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
// 使用更兼容的加载方式
if (!WebAssembly.instantiateStreaming) {
WebAssembly.instantiateStreaming = async (resp, importObject) => {
const source = await (await resp).arrayBuffer();
return await WebAssembly.instantiate(source, importObject);
};
}
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject)
.then((result) => {
go.run(result.instance);
})
.catch((err) => {
console.error("WASM加载失败:", err);
});
</script>
</head>
<body>
<h2>WebAssembly content</h2>
<div id="hello"></div>
</body>
</html>
4. 完整的 Go 代码示例
确保 Go 代码正确处理 JavaScript 交互:
package main
import (
"syscall/js"
)
func main() {
// 等待文档加载完成
doc := js.Global().Get("document")
// 检查元素是否存在
element := doc.Call("getElementById", "hello")
if !element.IsNull() {
element.Set("innerHTML", "Hello Wasm from Go 1.16+!")
}
// 防止程序退出
select {}
}
5. 验证版本兼容性
创建一个测试文件验证 Go 版本:
// version_check.go
package main
import (
"fmt"
"runtime"
"syscall/js"
)
func main() {
version := fmt.Sprintf("Go version: %s\nGOOS: %s\nGOARCH: %s",
runtime.Version(), runtime.GOOS, runtime.GOARCH)
js.Global().Get("console").Call("log", version)
doc := js.Global().Get("document")
doc.Call("getElementById", "hello").Set("innerHTML", version)
select {}
}
构建并测试:
GOOS=js GOARCH=wasm go build -o main.wasm version_check.go
6. 使用正确的 HTTP 服务器头
确保 HTTP 服务器正确设置 WASM MIME 类型:
# 使用 Python 启动服务器,确保正确的 MIME 类型
python3 -c "
import http.server
import socketserver
class Handler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header('Access-Control-Allow-Origin', '*')
if self.path.endswith('.wasm'):
self.send_header('Content-Type', 'application/wasm')
super().end_headers()
with socketserver.TCPServer(('', 8080), Handler) as httpd:
print('Serving at http://localhost:8080')
httpd.serve_forever()
"
关键点
- 版本匹配:
wasm_exec.js必须与 Go 编译器版本完全匹配 - 构建环境:确保
GOOS=js GOARCH=wasm环境变量正确设置 - MIME 类型:HTTP 服务器必须为
.wasm文件设置正确的 MIME 类型 - 浏览器缓存:测试前清除浏览器缓存,或使用无痕模式
执行上述步骤后,你的 WebAssembly 应用应该能在 Go 1.16+ 版本中正常工作。

