Golang与WebAssembly中syscall/js的问题探讨
Golang与WebAssembly中syscall/js的问题探讨
使用Go和WebAssembly时遇到的syscall/js问题
我正在研究WebAssembly,觉得Go比Rust更有意思,但还没走多远就遇到了一个大问题。
似乎由于某种原因我无法使用syscall/js。我第一个简单的hello world示例运行得很好,其他Go项目也能正常运行,所以我很确定我的环境没问题。但一旦我尝试使用js对象,一切就都崩溃了。
我的HTML页面如下:
<html>
<head>
<meta charset="utf-8">
<title>Go WebAssembly Demo</title>
</head>
<body>
<script src="wasm_exec.js"></script>
<script>
if (!WebAssembly.instantiateStreaming) { // polyfill
WebAssembly.instantiateStreaming = async (resp, importObject) => {
const source = await (await resp).arrayBuffer();
return await WebAssembly.instantiate(source, importObject);
};
}
const go = new Go();
let mod, inst;
WebAssembly.instantiateStreaming(fetch("lib.wasm"), go.importObject).then(async (result) => {
mod = result.module;
inst = result.instance;
await go.run(inst)
});
</script>
</body>
</html>
我的Go代码如下:
package main
import "syscall/js"
// import "syscall/js"
func add(i []js.Value) {
js.Global().Set("output", js.ValueOf(i[0].Int()+i[1].Int()))
println(js.ValueOf(i[0].Int() + i[1].Int()).String())
}
func subtract(i []js.Value) {
js.Global().Set("output", js.ValueOf(i[0].Int()-i[1].Int()))
println(js.ValueOf(i[0].Int() - i[1].Int()).String())
}
func registerCallbacks() {
js.Global().Set("add", js.NewCallback(add))
js.Global().Set("subtract", js.NewCallback(subtract))
}
func main() {
c := make(chan struct{}, 0)
println("WASM Go Initialized")
registerCallbacks()
<-c
}
我使用这个命令构建代码:
GOARCH=wasm GOOS=js go build -o lib.wasm main.go
在浏览器中使用syscall/js时出现的错误是:
Unhandled Promise Rejection: TypeError: this._inst.exports.getsp is not a function. (In 'this._inst.exports.getsp()', 'this._inst.exports.getsp' is undefined)
我没有遇到任何编译错误,go build也为我生成了lib.wasm文件。所有不包含syscall/js的代码都能正常工作。我在这里做错了什么?
更多关于Golang与WebAssembly中syscall/js的问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
按照您指出的方法替换 Wasm_exec.js 文件后,问题就解决了。我猜从教程下载的那个文件不起作用,而且我完全不知道它其实已经自带了。天啊,我完全找错了方向,之前还一直以为是 syscall/js 的问题。
感谢!
更多关于Golang与WebAssembly中syscall/js的问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你好 Jonas,
我最近关于 WebAssembly 的帖子包含了我 GitHub 上两个可运行示例的代码链接。这会向你展示如何入门。
看起来你正在使用 TutorialEdge 的 WebAssembly “计算器” 示例。(https://tutorialedge.net/golang/go-webassembly-tutorial/)我和论坛上的其他一些人尝试过这个示例,它对我们有效。(除了一个小问题。)
我不能完全确定,但看起来可能是你的 JavaScript 胶水代码有问题。我的处理方式是复制 $GOROOT/misc/wasm 中的 wasm_exec.js 文件。那里还有一个 HTML 文件,展示了如何在你的 HTML 页面中包含该文件和一些额外的 JavaScript 胶水代码(你在第一个代码清单中展示了这部分内容)。我使用了最新 Go 发行版(1.11.2)中的 HTML,并做了两处修改:
- 在
WebAssembly.instantiateStreaming(fetch(<wasm_file>) ...)调用中将 wasm 文件名改为 lib.wasm - 删除这一行:
document.getElementById("runButton").disabled = false;
无论如何,这就是我的做法。我不知道这是否完全正确,因为正如我报告的那样,我在某些操作系统/浏览器组合上遇到了问题。但它几乎总是有效的。这是我目前能提供的最佳方案,我正在等待是否会有更多回复,然后再去 Go 邮件列表提问或提交问题报告。


