Go 1.21+才原生支持GOOS=wasm GOARCH=wasm编译纯WASM模块,低于该版本会静默失败或报错;必须执行go version确认含go1.21或更高,否则须升级Go,不可复用旧版wasm_exec.js。

确认 Go 版本是否支持 WASM 原生编译
Go 1.21+ 才真正原生支持 GOOS=wasm GOARCH=wasm 编译纯 WASM 模块;低于该版本(比如 1.20 或更早)用这个组合会静默失败或报错 build constraints exclude all Go files —— 这不是你代码写错了,是工具链根本不认识这个目标。
执行 go version 确认输出含 go1.21 或更高。若不满足,必须升级 Go,别试图打补丁或复用旧版 wasm_exec.js 方案。
-
GOOS=js GOARCH=wasm是过时写法,Go 1.21 起已废弃,继续用会生成兼容性差、体积大、调试难的混合产物 - 新版编译结果是纯
.wasm文件,无 JS 胶水代码,加载逻辑需自行实现或借助社区 loader(如webassemblyjs) - 旧教程里反复出现的
$GOROOT/misc/wasm/wasm_exec.js在 Go 1.21+ 中已移除,硬拷贝会报错ReferenceError: Go is not defined
编译命令必须用 GOOS=wasm GOARCH=wasm
这是唯一有效的组合,且必须显式传入,不能靠环境变量全局设置——因为一旦设成 GOOS=wasm,后续所有 go build 都会默认走 WASM 目标,连本地测试都会失败。
正确写法:GOOS=wasm GOARCH=wasm go build -o main.wasm main.go
立即学习“go语言免费学习笔记(深入)”;
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 不加
-o会默认输出main.wasm,但建议明确指定,避免和已有文件冲突 - 不能用
go run:WASM 模块无法直接运行,必须由浏览器或 runtime 加载 - 禁用
net/http、os/exec、syscall等依赖系统调用的包——它们在 WASM 沙箱里根本不存在 -
fmt.Println仍可用,但输出到浏览器console,不是终端;想捕获日志需重定向log.SetOutput到js.Global().Get("console").Call("log")
main() 必须阻塞,否则瞬间退出
WASM 模块启动后执行 main(),然后立即终止——这会导致注册的 JS 回调(如 js.Global().Set("foo", js.FuncOf(...)))根本没机会被调用。
必须用 js.Wait() 阻塞主线程,这是 Go 1.21+ 的标准做法(旧版用 select{} 已不推荐)。
- 示例最小可运行结构:
package main import "syscall/js" func main() { js.Global().Set("add", js.FuncOf(func(this js.Value, args []js.Value) interface{} { return args[0].Int() + args[1].Int() })) js.Wait() // 关键:没有这行,函数注册无效 } - 如果用了
js.Wait()还报错,检查是否漏了import "syscall/js"—— 它不是可选包,是 WASM 交互唯一官方通道 - 不要在
main()里写耗时同步逻辑(如循环计算),会卡死 UI;复杂任务应拆成异步回调或配合js.Timeout
WASM 文件不能双击打开,必须走 HTTP 服务
浏览器禁止 file:// 协议加载 WASM,直接双击 HTML 会看到 Failed to instantiate WebAssembly module: CompileError 或更模糊的网络错误,本质是跨域策略拦截。
本地开发只需起一个轻量 HTTP 服务:python3 -m http.server 8080(Python)、serve -s .(npm serve)或 Go 自带的 go run -m httpserver(需额外写几行)。
- HTML 中加载必须用
fetch("main.wasm")或WebAssembly.instantiateStreaming(),不能用new WebAssembly.Module()(需要 ArrayBuffer) - 若用
WebAssembly.instantiateStreaming(),确保服务器返回Content-Type: application/wasm,否则 Chrome 会拒绝解析 - 常见坑:Nginx/Apache 默认不识别
.wasm后缀,需手动添加 MIME 类型配置
js.Wait() 不是可选装饰,而是存活前提;HTTP 服务不是开发便利,而是强制要求;而 GOOS=wasm GOARCH=wasm 这八个字符,写错一个就全盘失效。**

















