go 1.21+ 是硬门槛,低于它无法运行 wasm;唯一合法编译组合是 goos=wasm goarch=wasm;必须调用 js.wait() 阻塞主线程;需通过 http 服务加载,且 content-type 必须为 application/wasm。

Go 1.21+ 是硬门槛,低于它根本跑不起来
如果你用的是 go1.20 或更早版本,GOOS=wasm GOARCH=wasm go build 会静默失败或报错 build constraints excluded all Go files——这不是配置问题,是版本不支持。官方从 go1.21 才开始原生支持纯 WASM 编译(即不依赖 syscall/js 的 GOOS=js 路线)。确认方式只有一条:go version 输出必须含 go1.21 或更高。别试降级兼容、别装 emsdk、别 patch 工具链,升级 Go 就完事。
GOOS=wasm GOARCH=wasm 是唯一合法组合
GOOS=js 已废弃,继续用会生成带 wasm_exec.js 胶水层的老式模块,且与新版 runtime 不兼容。GOOS=wasi 或 GOARCH=wasip1 看起来很新潮,但 Go 官方截至 go1.23 仍不支持——编译直接报错或产出不可加载的二进制。正确命令只有这一种:GOOS=wasm GOARCH=wasm go build -o main.wasm main.go。产物是纯 .wasm 字节码,没 JS、没胶水、没 main 函数入口符号,必须靠宿主环境(比如浏览器)显式加载并传入 import object。
不调 js.Wait() 就等于没写 main
WASM 模块启动后执行 main(),然后立刻退出。常见错误是写完逻辑就 return,结果浏览器控制台只闪一下 fmt.Println 就消失。必须在 main() 末尾加:js.Wait()。它不是“等待某个事件”,而是永久阻塞主线程,让 Go runtime 保持活跃,否则所有注册的回调(比如按钮点击 handler)全失效。注意:select{} 在 GOOS=wasm 下无效,会 panic;time.Sleep 也不起作用——只有 js.Wait() 是正解。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
本地双击 HTML 必然失败,必须走 HTTP 服务
浏览器禁止 file:// 协议加载 WASM,直接双击打开 HTML 会卡在 WebAssembly.instantiateStreaming() failed 或更模糊的网络错误。这不是代码 bug,是安全策略。解决办法只有:启动一个最小 HTTP 服务。推荐用 goexec "http.ListenAndServe(`:8080`, http.FileServer(http.Dir(`.`)))"(需先 go install github.com/shurcooL/goexec@latest),或 python3 -m http.server 8080。另外注意:Content-Type 必须为 application/wasm,Python 自带服务器默认支持,Node 或自建服务需手动设置。
真正容易被忽略的点在于:js.Wait() 之后,所有 DOM 操作都得通过 js.Global().Get("document") 桥接,标准库的 os、net/http、log 全部不可用;而日志重定向、错误捕获、甚至 panic 处理,都得自己用 js.Global().Call("console.error") 手动兜底——这些不是“高级技巧”,是能跑起来的前提。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










