Go编译WASM后如何在HTML中调用导出的FuncName函数
解决Go WASM导出函数无法在浏览器中调用的问题
一、标准Go编译的解决方案
1. 确保依赖文件正确
使用Go SDK自带的wasm_exec.js,路径为$GOROOT/misc/wasm/wasm_exec.js,不要使用第三方版本,避免兼容性问题。
2. 调整JS调用逻辑
Go编译的WASM导出函数无法直接接收JS数组,需要通过内存拷贝传递切片参数,且必须在go.run()执行完成后调用导出函数(确保Go runtime初始化完成)。修改后的JS代码如下:
<script src="./wasm_exec.js"></script> <script> const go = new Go(); let wasmInstance; WebAssembly.instantiateStreaming(fetch("./file.wasm"), go.importObject) .then((result) => { wasmInstance = result.instance; // 先执行Go的main函数,完成runtime初始化 go.run(wasmInstance); // 准备调用参数 const M = 5; const durations = [1, 2, 3, 4, 5]; // 步骤1:在Go内存中分配数组空间(每个int占4字节) const arrayByteSize = durations.length * 4; const arrayPtr = wasmInstance.exports.malloc(arrayByteSize); // 步骤2:将JS数组的值写入Go内存 const memView = new Uint32Array(wasmInstance.exports.memory.buffer); for (let i = 0; i < durations.length; i++) { memView[arrayPtr / 4 + i] = durations[i]; } // 步骤3:调用导出函数(注意:Go切片会被拆分为指针+长度两个参数) const returnVal = wasmInstance.exports.FuncName(M, arrayPtr, durations.length); console.log("Go函数返回值:", returnVal); // 步骤4:释放Go内存(避免内存泄漏) wasmInstance.exports.free(arrayPtr); }) .catch(err => console.error("加载WASM失败:", err)); </script>
3. 验证Go函数导出
你的Go代码导出逻辑无需修改,但要注意:Go的//export注释必须紧跟函数定义,且函数必须在main包中。
二、TinyGo编译的解决方案
1. 修正编译命令
必须添加-target wasm参数,否则编译出的WASM无法在浏览器中正常工作:
tinygo build -target wasm -o path_to/file.wasm path_to/file.go
2. 使用TinyGo专属的wasm_exec.js
TinyGo的wasm_exec.js与标准Go的不兼容,需从TinyGo安装目录中获取,路径通常为tinygo/targets/wasm_exec.js,替换HTML中的对应文件。
3. 更便捷的参数传递(可选)
如果使用TinyGo,可以借助syscall/js包直接处理JS值,无需手动操作内存:
package main import ( "fmt" "syscall/js" ) //export FuncName func FuncName(this js.Value, args []js.Value) interface{} { M := args[0].Int() durationsJS := args[1] durations := make([]int, durationsJS.Length()) for i := 0; i < durationsJS.Length(); i++ { durations[i] = durationsJS.Index(i).Int() } fmt.Println("[GO] Log file.go", M, durations) return 10 } func main() { // 阻塞主线程,保持WASM实例活跃 select {} }
对应的JS调用代码:
<script src="./wasm_exec.js"></script> <script> const go = new Go(); WebAssembly.instantiateStreaming(fetch("./file.wasm"), go.importObject) .then((result) => { go.run(result.instance); // 直接传递JS数值和数组 const returnVal = result.instance.exports.FuncName(5, [1,2,3,4,5]); console.log("返回值:", returnVal); }); </script>
三、通用检查项
- 检查浏览器控制台是否有404错误,确保
wasm_exec.js和file.wasm的路径正确。 - 确认编译命令中的输出路径与HTML中请求的路径一致。
- 若使用标准Go,确保编译时的
GOOS=js GOARCH=wasm环境变量正确设置。
内容的提问来源于stack exchange,提问作者Baelfire18
相关产品推荐
相关产品推荐

