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

Go开发WASM时注册供JS调用的函数报undefined错误怎么解决?

问题根因汇总

两个案例的核心问题都和WASM异步加载的执行时序相关,附加少量API调用错误:


1. 标准Go WASM案例问题

原因

你在HTML底部的console.log(sub(5,3))是同步执行的,而WASM的加载、实例化、执行Go main函数的全流程都是异步操作:

  • loadWasm.js里的init是异步函数,fetch下载WASM文件、WebAssembly.instantiateStreaming实例化、go.run执行Go代码都是异步任务
  • 当你同步调用sub时,Go main函数里的js.Global().Set("sub", js.FuncOf(sub))还没执行,全局作用域下自然没有sub函数,触发undefined错误。

修复方案

把调用sub的逻辑推迟到WASM加载完成后执行,修改方式如下:
第一步:修改loadWasm.js,在WASM初始化完成后抛出自定义事件通知页面:

async function init(){
    const go = new Go();
    const result = await WebAssembly.instantiateStreaming(
        fetch("http://localhost:8080/www/main.wasm"),
        go.importObject
    );
    go.run(result.instance);
    // 抛出加载完成事件
    window.dispatchEvent(new CustomEvent('wasmInitDone'));
}
init();

第二步:修改HTML中的调用逻辑,监听加载完成事件后再调用sub:

<script>
window.addEventListener('wasmInitDone', () => {
    console.log(sub(5,3));
})
</script>

2. TinyGo WASM案例问题

原因

存在三个错误点:

  1. 时序问题和标准Go案例一致:你在代码末尾同步调用console.log('multiplied two numbers:', exports.multiply(5, 3));时,WASM还没完成实例化,导出函数还不可用
  2. 导出函数取值错误:没有声明过exports变量,TinyGo导出的函数挂载在WebAssembly.instantiate返回的实例obj.instance.exports上
  3. 资源路径错误:你编译生成的WASM文件是main2.wasm,但代码里填的WASM_URL = 'main.wasm',会返回404加载失败。

修复方案

修改JS代码如下:

const go = new Go(); // Defined in wasm_exec.js

go.importObject.env = {
    'main.add': function(x, y) {
        return x + y
    }
}

// 修正WASM路径
const WASM_URL = 'main2.wasm';
var wasm;

function callMultiply() {
    console.log('multiplied two numbers:', wasm.exports.multiply(5, 3));
}

if ('instantiateStreaming' in WebAssembly) {
    WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) {
        wasm = obj.instance;
        go.run(wasm);
        // 实例化完成后再调用导出函数
        callMultiply();
    })
} else {
    fetch(WASM_URL).then(resp =>
        resp.arrayBuffer()
    ).then(bytes =>
        WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {
            wasm = obj.instance;
            go.run(wasm);
            // 实例化完成后再调用导出函数
            callMultiply();
        })
    )
}

额外注意:TinyGo的//export注释和函数定义之间不能有空行,你现有代码的写法是符合要求的。


内容的提问来源于stack exchange,提问作者Hasan A Yousef

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:45:02