[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-wazero-turns-go-wasm-into-plain-go-zh":3,"article-related-wazero-turns-go-wasm-into-plain-go-zh":31,"series-tools-137212d6-7843-4f65-b19f-f0db62e1929b":78},{"id":4,"slug":5,"title":6,"content":7,"summary":8,"source":9,"source_url":10,"author":11,"image_url":12,"cover_image":12,"category":13,"language":14,"translated_content":11,"related_article_id":15,"keywords":16,"key_takeaways":23,"views":27,"created_at":28,"published_at":29,"topic_cluster_id":30},"137212d6-7843-4f65-b19f-f0db62e1929b","wazero-turns-go-wasm-into-plain-go-zh","Wazero 讓 Go Wasm 變回純 Go","\u003Cp data-speakable=\"summary\">這篇整理 wazero 在 Go 專案裡怎麼用、什麼情境最適合、以及可以直接貼上的最小模板。\u003C\u002Fp>\u003Cp>我用 Go 跑 WebAssembly 一陣子了。理論上很美，實際上很煩。你明明只是想在 Go 服務裡跑一個 wasm 模組，結果一下要顧 CGO，一下要顧交叉編譯，一下又冒出一堆「先把這個原生依賴裝好」的前置條件。Go 本來最討厭的就是這種黏黏的東西，偏偏很多 runtime 就愛把事情搞複雜。我後來才發現，我不是在找最強的 runtime，我是在找一個不要跟 Go 作對的 runtime。\u003C\u002Fp>\u003Cp>這次我拆的是 \u003Ca href=\"https:\u002F\u002Fwasmruntime.com\u002Fen\u002Flanguages\u002Fgo\">wasmRuntime 的 Go WebAssembly runtime 指南\u003C\u002Fa>，它的推薦很直接：Go 專案先看 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ftetratelabs\u002Fwazero\">wazero\u003C\u002Fa>。不是因為它最花俏，而是因為它夠乾淨，乾淨到你不太需要跟 build system 打架。這種選型我很買單，因為我維護服務的時候，最怕的不是少一個功能，是多一個我根本不想處理的坑。\u003C\u002Fp>\u003Ch2>Wazero 的重點不是強，是不鬧事\u003C\u002Fh2>\u003Cblockquote>「Wazero is a zero-dependency WebAssembly runtime for Go applications.」\u003C\u002Fblockquote>\u003Cp>翻譯一下就是：它是給 Go 用的，而且盡量不要把你拖進額外依賴地獄。這句話看起來很普通，但對 Go 開發者來說超重要。Go 的爽感就是編譯、部署、交叉編譯都盡量一致；一旦 runtime 開始依賴 CGO，整個故事就會變味。你本來只想處理 wasm，最後卻在處理系統套件、編譯器版本、容器映像檔差異。\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781681649267-d64h.png\" alt=\"Wazero 讓 Go Wasm 變回純 Go\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003Cp>我自己最受不了的就是這種「可以用，但要先補一堆條件」的工具。你在本機跑得動，不代表 CI 跑得動；CI 跑得動，不代表 ARM \u003Ca href=\"\u002Fnews\u002Fveritas-robot-policy-visual-verification-zh\">機器\u003C\u002Fa>跑得動。wazero 的價值就在這裡，它把 runtime 層拉回 Go 自己的語言邏輯裡，不逼你另外學一套部署宗教。\u003C\u002Fp>\u003Cp>實操寫法很簡單：如果你的需求是「在 Go 服務裡載入 wasm、呼叫 exported function、做 sandbox 或 plugin 執行」，我會先從 wazero 開始。不要先去追那些看起來很潮的 runtime，先確認你到底是不是只需要一個能穩穩跑的執行層。\u003C\u002Fp>\u003Cul>\u003Cli>Go-first 專案，先選純 Go runtime。\u003C\u002Fli>\u003Cli>要做嵌入式 wasm，先避開 CGO。\u003C\u002Fli>\u003Cli>如果目標是少維運成本，wazero 很合適。\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>純 Go 不是加分項，是門檻\u003C\u002Fh2>\u003Cblockquote>「Pure Go implementation means no CGO, easy cross-compilation, and Go-native integration.」\u003C\u002Fblockquote>\u003Cp>這句我會直接翻成白話：你不用另外養一條原生工具鏈，能省掉一堆莫名其妙的部署問題。這不是什麼漂亮口號，這是實際維運時會救命的事。很多 runtime 的問題不是功能不夠，是它把你的 build 流程搞得像拼圖。今天少一個 library，明天少一個 header，後天容器裡還少一個系統套件。\u003C\u002Fp>\u003Cp>我以前在一個團隊看過很典型的狀況：大家都說「只是加一個 wasm 執行能力」，結果最後 CI pipeline 多了幾個步驟，\u003Ca href=\"\u002Ftag\u002Fdocker\">Docker\u003C\u002Fa> image 也膨脹，發版時還要確認不同平台的原生依賴。那種感覺很像你只是想換燈泡，結果被迫重拉全屋電線。wazero 至少不會逼你先做這些事。\u003C\u002Fp>\u003Cp>實操上，我會把「是否純 Go」當成第一道篩選條件。只要你的服務有多架構部署、靜態編譯、容器化發版，這個條件就不是偏好，是硬需求。你可以先不管誰 \u003Ca href=\"\u002Ftag\u002Fbenchmark\">benchmark\u003C\u002Fa> 比較漂亮，先問自己：這個 runtime 會不會讓我在 build 階段多養一個世界？如果答案是會，先放一邊。\u003C\u002Fp>\u003Cul>\u003Cli>需要多平台部署，就先看純 Go。\u003C\u002Fli>\u003Cli>需要穩定 CI，就先避開 CGO。\u003C\u002Fli>\u003Cli>需要可預期的交叉編譯，就別讓 runtime 亂加戲。\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>它的 API 夠直白，才像 Go\u003C\u002Fh2>\u003Cblockquote>\u003Cpre>\u003Ccode>package main\n\nimport (\n    \"context\"\n    \"os\"\n\n    \"github.com\u002Ftetratelabs\u002Fwazero\"\n    \"github.com\u002Ftetratelabs\u002Fwazero\u002Fimports\u002Fwasi_snapshot_preview1\"\n)\n\nfunc main() {\n    ctx := context.Background()\n    r := wazero.NewRuntime(ctx)\n    defer r.Close(ctx)\n\n    wasi_snapshot_preview1.MustInstantiate(ctx, r)\n    wasm, _ := os.ReadFile(\"module.wasm\")\n    mod, _ := r.InstantiateModuleFromBinary(ctx, wasm)\n    result, _ := mod.ExportedFunction(\"add\").Call(ctx, 1, 2)\n    println(result[0])\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fblockquote>\u003Cp>這段我很喜歡，因為它沒有把簡單事情寫成儀式。建立 runtime、載入 wasm、呼叫函式、收尾，整個流程都很像 Go 本來就該長的樣子。你不需要先學一堆抽象名詞，也不用在文件裡翻半天才知道「到底要不要先啟用 WASI」。這裡直接寫出來，反而省事。\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781681633962-hqqe.png\" alt=\"Wazero 讓 Go Wasm 變回純 Go\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003Cp>我之前踩過一個坑：某個模組明明只是要跑一個小函式，卻因為 host capability 的設定不清楚，整個整合卡了半天。最後不是程式邏輯錯，而是我根本沒搞懂 runtime 預設幫我做了什麼。wazero 的好處是，它把這些東西攤在你眼前，讓你知道自己到底在接什麼。\u003C\u002Fp>\u003Cp>實操寫法就是先縮小範圍。不要一開始就想把整個產品流程都塞進 wasm。先做一個模組、一個 exported function、必要時再加 WASI。你先把最小可行路徑跑通，後面要擴充才有底。\u003C\u002Fp>\u003Ch2>WASI 要用就明講，不要裝沒事\u003C\u002Fh2>\u003Cblockquote>「WASI Preview 1 only. No Component Model yet.」\u003C\u002Fblockquote>\u003Cp>這句其實很誠實，也很重要。wazero 不是什麼都能吞的萬能解法，它比較像一把乾淨的刀，切得漂亮，但有邊界。你如果現在的需求是標準支援更廣、Component Model 已經是你路線圖上的重點，那你就不能\u003Ca href=\"\u002Fnews\u002Fqualcomm-bets-on-ai-devices-over-apps-zh\">只看\u003C\u002Fa>「純 Go 很爽」這一點。\u003C\u002Fp>\u003Cp>白話一點講，wazero 很適合「我想在 Go 裡執行 wasm」這件事，但不適合你把它當成「我要追最新 Wasm 規格全餐」的答案。這兩件事差很多。前者是務實需求，後者是架構野心。很多團隊的問題就是把野心當需求，最後選了不合適的 runtime，然後怪工具不夠好。\u003C\u002Fp>\u003Cp>我會怎麼做？先列需求清單，而且只列今天真的要用的。你如果目前只是要載入模組、呼叫函式、處理少量 host 互動，那 wazero 很合理。你如果已經確定要碰 Component Model、要更完整的標準相容性，那就別硬撐，直接把 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fbytecodealliance\u002Fwasmtime\">Wasmtime\u003C\u002Fa> 拉進比較表。\u003C\u002Fp>\u003Cul>\u003Cli>先確認你需要的是 WASI Preview 1 還是別的版本。\u003C\u002Fli>\u003Cli>先確認你的模組有沒有 Component Model 需求。\u003C\u002Fli>\u003Cli>先確認你要的是執行穩定，還是規格覆蓋更廣。\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>別拿 runtime 清單當戰利品牆\u003C\u002Fh2>\u003Cblockquote>「Other options: Wasmtime, Wasmer, WasmEdge, Spin, GraalWasm, Wasm3, WAMR, Wasmi, Chicory, Lunatic.」\u003C\u002Fblockquote>\u003Cp>我很討厭一種比較方式：把一堆 runtime 排成表，然後假裝只要欄位多一點就代表更好。事實不是這樣。runtime 不是蒐集品，你不需要因為有很多選項就覺得自己選到了最厲害的。你要看的只有一件事：它是不是符合你現在的 host 語言、部署方式、以及你能接受的維運成本。\u003C\u002Fp>\u003Cp>這份指南最有用的地方，就是它沒有裝中立。它其實很明確地說，對 Go 來說，wazero 是最順的起點。這種講法我反而比較信，因為它不是在賣夢，而是在講工作流。Go 開發者最怕的不是少功能，而是多一層沒必要的複雜度。\u003C\u002Fp>\u003Cp>實操寫法我會建議這樣做：先用你的最強約束來選。你的最強約束如果是「純 Go」，那就是 wazero。你的最強約束如果是「規格支援更完整」，那就看 Wasmtime。你的最強約束如果是別的，例如 AI 推論或特殊嵌入場景，再去看其他候選。不要反過來，先把所有候選看完再頭痛。\u003C\u002Fp>\u003Ch2>我會怎麼落地這個決定\u003C\u002Fh2>\u003Cp>如果只是要我給一句結論，我會說：Go 專案裡要跑 wasm，先用 wazero。原因不是它最炫，而是它最像 Go。你不用為了 runtime 改整個 build 流程，也不用把部署故事拆成兩套。這種「少一個維運問題」的價值，通常比多一個漂亮功能更實際。\u003C\u002Fp>\u003Cp>但我也不會把它吹成萬靈丹。你只要需求一碰到 Component Model、更新的 Wasm 規格、或你很在意某些進階標準支援，就要重新評估。這不是退讓，這是正常選型。工具本來就該為需求服務，不是反過來。\u003C\u002Fp>\u003Cp>我自己的判斷順序很固定：先看是不是純 Go，再看是不是要 CGO，再看 wasm 特性覆蓋範圍，最後才看文件風格跟社群熱度。因為前面三個如果不對，後面再熱鬧都沒用。你終究還是得把它塞進 CI、塞進容器、塞進真實服務裡跑。\u003C\u002Fp>\u003Ch2>可抄的模板\u003C\u002Fh2>\u003Cpre>\u003Ccode># Go + wazero 最小可用模板\n\n## 什麼時候用\n我會在這種情況用它：\n- 需要在 Go 服務裡執行 WebAssembly\n- 想避免 CGO\n- 想保留交叉編譯與靜態部署的簡潔性\n- 先從最小功能驗證，不想一開始就把架構做大\n\n## 安裝\nbash\ngo get github.com\u002Ftetratelabs\u002Fwazero\n\n\n## 最小程式\ngo\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"os\"\n\n    \"github.com\u002Ftetratelabs\u002Fwazero\"\n    \"github.com\u002Ftetratelabs\u002Fwazero\u002Fimports\u002Fwasi_snapshot_preview1\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    runtime := wazero.NewRuntime(ctx)\n    defer runtime.Close(ctx)\n\n    \u002F\u002F 只有模組真的需要 WASI 才開。\n    wasi_snapshot_preview1.MustInstantiate(ctx, runtime)\n\n    wasmBytes, err := os.ReadFile(\"module.wasm\")\n    if err != nil {\n        panic(err)\n    }\n\n    mod, err := runtime.InstantiateModuleFromBinary(ctx, wasmBytes)\n    if err != nil {\n        panic(err)\n    }\n\n    fn := mod.ExportedFunction(\"add\")\n    if fn == nil {\n        panic(\"找不到 exported function: add\")\n    }\n\n    results, err := fn.Call(ctx, 1, 2)\n    if err != nil {\n        panic(err)\n    }\n\n    fmt.Println(results[0])\n}\n\n\n## 我自己的檢查清單\n- 先確認模組真的需要哪個 WASI 版本\n- 先只接一個 exported function\n- 先只跑一條執行路徑，不要一次接整個產品流程\n- 先確認 CI、容器、交叉編譯都能過\n- 只要沒有硬需求，就先維持純 Go，不要碰 CGO\n\n## 選型規則\n選 wazero，如果：\n- 你是 Go-first 專案\n- 你在意部署簡單\n- 你在意交叉編譯\n- 你暫時不需要 Component Model\n\n改看 Wasmtime，如果：\n- 你需要更完整的標準支援\n- 你已經確定要碰 Component Model\n- 你能接受 CGO 或較重的建置鏈\n\n## 最後一步\n先把這段接到一個內部工具、單一插件入口，或一條 sandbox 執行路徑上，確認真的有價值，再決定要不要擴大。\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>這個模板我刻意寫得很小，因為我真的不想再看那種一上來就包三層抽象、結果沒人敢改的範例。能跑、能懂、能複製，這三件事比「看起來很完整」重要太多。你先把它塞進 \u003Ca href=\"\u002Fnews\u002Freprorepo-github-issues-reproducibility-audits-zh\">repo\u003C\u002Fa>，真的跑過一次，再來談要不要擴充。\u003C\u002Fp>\u003Cp>來源我主要拆的是 \u003Ca href=\"https:\u002F\u002Fwasmruntime.com\u002Fen\u002Flanguages\u002Fgo\">wasmRuntime 的 Go WebAssembly runtime 指南\u003C\u002Fa>，原始推薦邏輯與比較框架來自那篇內容；wazero 相關資訊可看 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ftetratelabs\u002Fwazero\">wazero GitHub\u003C\u002Fa>，替代方案可看 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fbytecodealliance\u002Fwasmtime\">Wasmtime GitHub\u003C\u002Fa>，Wasm 與 WASI 的背景則可參考 \u003Ca href=\"https:\u002F\u002Fwebassembly.org\u002F\">WebAssembly\u003C\u002Fa> 和 \u003Ca href=\"https:\u002F\u002Fwasi.dev\u002F\">WASI\u003C\u002Fa>。我這篇有做整理、白話化跟實作模板化，其他都是基於原始資料延伸出來的。\u003C\u002Fp>","我拆解 wazero 的 Go Wasm 選型邏輯，整理成純 Go、免 CGO、可直接套用的實作模板。","wasmruntime.com","https:\u002F\u002Fwasmruntime.com\u002Fen\u002Flanguages\u002Fgo",null,"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781681649267-d64h.png","tools","zh","33c54a94-00ba-4029-bd8d-67b27812d487",[17,18,19,20,21,22],"wazero","Go","WebAssembly","WASI","純 Go","CGO",[24,25,26],"wazero 最適合 Go-first、需要純 Go 與免 CGO 的 WebAssembly 場景。","先用需求篩選 runtime：純 Go、交叉編譯、WASI 版本、Component Model。","可直接套用最小模板，先把單一 wasm 模組接進 Go 服務再擴充。",0,"2026-06-17T07:33:30.509996+00:00","2026-06-17T07:33:30.501+00:00","c3c88dd2-a940-438a-b359-0e5a24562273",{"tags":32,"relatedLang":37,"relatedPosts":41},[33,35],{"name":18,"slug":34},"go",{"name":19,"slug":36},"webassembly",{"id":15,"slug":38,"title":39,"language":40},"wazero-turns-go-wasm-into-plain-go-en","Wazero turns Go Wasm into plain Go","en",[42,48,54,60,66,72],{"id":43,"slug":44,"title":45,"cover_image":46,"image_url":46,"created_at":47,"category":13},"6c40b201-8e6d-4b48-a988-791936798713","opencode-terminal-ai-coding-loop-zh","OpenCode 讓終端編碼變成迴圈","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781693320715-b9x5.png","2026-06-17T10:47:58.3922+00:00",{"id":49,"slug":50,"title":51,"cover_image":52,"image_url":52,"created_at":53,"category":13},"2830e8de-b146-4dd7-b1f6-1b61c223e9ea","open-source-ai-software-infrastructure-wins-zh","開源 AI 軟體贏在基礎設施，不贏在話題","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781691476387-1uwa.png","2026-06-17T10:17:26.854039+00:00",{"id":55,"slug":56,"title":57,"cover_image":58,"image_url":58,"created_at":59,"category":13},"c849204c-8427-4af7-9662-60aa9e1f5524","ffmpeg-webcli-browser-video-editor-zh","ffmpeg-webCLI 把剪片搬進瀏覽器","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781680695836-cdup.png","2026-06-17T07:17:40.422494+00:00",{"id":61,"slug":62,"title":63,"cover_image":64,"image_url":64,"created_at":65,"category":13},"b599d760-7066-4299-b304-3ae189fcd6e4","newcore-turns-ai-agents-into-managed-identities-zh","NewCore 把 AI agent 變成可管身份","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781676209869-hmt9.png","2026-06-17T06:02:59.513643+00:00",{"id":67,"slug":68,"title":69,"cover_image":70,"image_url":70,"created_at":71,"category":13},"b8952293-f38b-41ae-90ee-a1d244ae4738","kimi-k27-review-copyable-coding-playbook-zh","Kimi K2.7 把評測變可抄流程","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781673555614-b695.png","2026-06-17T05:18:37.659209+00:00",{"id":73,"slug":74,"title":75,"cover_image":76,"image_url":76,"created_at":77,"category":13},"ff413f46-82bf-4bcb-a256-2a4c24f76a2b","wikipedia-foss-packages-tool-map-zh","Wikipedia FOSS 清單變工具地圖","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1781663598319-0ubt.png","2026-06-17T02:32:56.642555+00:00",[79,84,89,94,99,104,109,114,119,124],{"id":80,"slug":81,"title":82,"created_at":83},"855cd52f-6fab-46cc-a7c1-42195e8a0de4","surepath-real-time-mcp-policy-controls-zh","SurePath 推出即時 MCP 政策控管","2026-03-26T07:57:40.77233+00:00",{"id":85,"slug":86,"title":87,"created_at":88},"9b19ab54-edef-4dbd-9ce4-a51e4bae4ebb","mcp-in-2026-the-ai-tool-layer-teams-use-zh","2026 年 MCP：團隊真的在用的 AI 工具層","2026-03-26T08:01:46.589694+00:00",{"id":90,"slug":91,"title":92,"created_at":93},"af9c46c3-7a28-410b-9f04-32b3de30a68c","prompting-in-2026-what-actually-works-zh","2026 提示工程，真正有用的是什麼","2026-03-26T08:08:12.453028+00:00",{"id":95,"slug":96,"title":97,"created_at":98},"05553086-6ed0-4758-81fd-6cab24b575e0","garry-tan-open-sources-claude-code-toolkit-zh","Garry Tan 開源 Claude Code 工具包","2026-03-26T08:26:20.068737+00:00",{"id":100,"slug":101,"title":102,"created_at":103},"042a73a2-18a2-433d-9e8f-9802b9559aac","github-ai-projects-to-watch-in-2026-zh","2026 必看 20 個 GitHub AI 專案","2026-03-26T08:28:09.619964+00:00",{"id":105,"slug":106,"title":107,"created_at":108},"a5f94120-ac0d-4483-9a8b-63590071ac6a","claude-code-vs-cursor-2026-zh","Claude Code 與 Cursor 深度對比：202…","2026-03-26T13:27:14.279193+00:00",{"id":110,"slug":111,"title":112,"created_at":113},"0975afa1-e0c7-4130-a20d-d890eaed995e","practical-github-guide-learning-ml-2026-zh","2026 機器學習入門 GitHub 實用指南","2026-03-27T01:16:49.712576+00:00",{"id":115,"slug":116,"title":117,"created_at":118},"bfdb467a-290f-4a80-b3a9-6f081afb6dff","aiml-2026-student-ai-ml-lab-repo-review-zh","AIML-2026：像課綱的學生實驗 Repo","2026-03-27T01:21:51.467798+00:00",{"id":120,"slug":121,"title":122,"created_at":123},"80cabc3e-09fc-4ff5-8f07-b8d68f5ae545","ai-trending-github-repos-and-research-feeds-zh","AI Trending：把 AI 資源收成一張表","2026-03-27T01:31:35.262183+00:00",{"id":125,"slug":126,"title":127,"created_at":128},"3ce6e6e2-bac5-463e-9f8d-45caabcc61f7","awesome-ai-for-science-research-tools-map-zh","AI 科研工具清單，開始像地圖了","2026-03-27T01:46:50.521945+00:00"]