You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 21:47:45