使用WebAssembly和Go创建快速Web应用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

WebAssembly 和 Go 入门



WebAssembly (Wasm) 是一种低级二进制指令格式,在浏览器中以接近原生的速度运行。结合 Go 语言 (Golang),您将获得一个用于创建高性能 Web 应用程序的强大工具。Go 可以编译为 WebAssembly,从而允许将复杂的计算、算法甚至游戏直接移植到浏览器中,而无需牺牲性能。



在本文中,我们将介绍如何配置环境、编写一个简单的 Go 模块、将其编译为 Wasm 并与 JavaScript 集成。您将了解关键包、限制和最佳实践。



配置 Go 编译为 Wasm 的环境



安装 Go 和 WebAssembly 依赖项



首先,确保您已安装 Go 1.11 或更高版本(建议使用 1.21+)。WebAssembly 开箱即用。编译时使用环境变量 GOOS=wasm GOARCH=wasm。



您还需要 Go 附带的 wasm_exec.js 支持文件。将其复制到项目根目录:



cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .


项目结构



创建一个简单的结构:



my-wasm-app/├── main.go├── wasm_exec.js├── index.html└── main.wasm (编译后创建)


为 WebAssembly 编写 Go 模块



简单示例:加法函数



创建包含以下内容的 main.go 文件:



package main

import ( "syscall/js")

func add(this js.Value, args []js.Value) interface{} { if len(args) < 2 { return 0 } a := args[0].Int() b := args[1].Int() return a + b}

func main() { c := make(chan struct{}, 0)

js.Global().Set("goAdd", js.FuncOf(add))

<-c}


这里我们使用 syscall/js 包与 JavaScript 交互。add 函数接受两个参数并返回它们的和。通道 c 阻止程序退出,使模块保持活动状态。



编译为 Wasm



执行命令:



GOOS=wasm GOARCH=wasm go build -o main.wasm main.go


结果将生成一个 main.wasm 文件,对于这个简单示例,大小约为 1-2 MB。在生产环境中,使用 -ldflags="-s -w" 标志来减小体积。



与 HTML 和 JavaScript 集成



创建 HTML 页面



创建 index.html 文件:



<!DOCTYPE html><html lang="zh"><head>    <meta charset="UTF-8">    <title>Go + WebAssembly</title>    <script src="wasm_exec.js"></script></head><body>    <h2>浏览器中的 Go 计算器</h2>    <input type="number" id="num1" value="5">    <input type="number" id="num2" value="10">    <button onclick="calculate()">相加</button>    <p>结果: <span id="result">0</span></p>

<script> const go = new Go(); WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject) .then((result) => { go.run(result.instance); console.log("WebAssembly 模块已加载"); });

function calculate() { const a = parseInt(document.getElementById('num1').value); const b = parseInt(document.getElementById('num2').value); const sum = goAdd(a, b); document.getElementById('result').innerText = sum; } </script></body></html>


请注意:由于在 Go 代码中调用了 js.Global().Set("goAdd", ...),函数 goAdd 变成了全局函数。



启动本地服务器

博客

书籍推荐