Wails 是什么
本教程共 42 篇 · 第 1 篇 · 更新于 2026-08-03
1. Wails 是什么
本节目标
- 用一句话说清 Wails 在解决什么问题
- 知道 Wails 能做什么、不适合做什么
- 看懂一个最小示例里 Go 和前端是怎么连起来的
- 判断你手上的项目值不值得用 Wails
1-1 一句话说清 Wails
Wails 是一个让你用 Go 写后端逻辑、用 Web 技术(HTML / CSS / 任意前端框架)写界面 来构建桌面应用的框架。最后一打包,出来的是一个原生的二进制文件,双击就能在 Windows、macOS、Linux 上跑,不需要用户装浏览器、装运行时。
如果你用过 Electron,这个故事就很熟悉了:左边是业务逻辑,右边是网页界面。区别在于,Electron 把一整个 Chromium 浏览器塞进安装包,而 Wails 直接复用操作系统自带的渲染引擎——Windows 上是 WebView2,macOS 上是系统的 WebKit,Linux 上是 GTK 的 WebKit。所以同样一个应用,Wails 的产物往往只有十几兆,而 Electron 动辄上百兆。
NoteWebView 是操作系统提供的网页渲染组件。说白了,它就是你系统里那个浏览器用来显示网页的”引擎核心”,只是不单独给你一个浏览器窗口。
换个角度理解:Wails 把”写网站”和”写桌面程序”这两件事缝合了。你不需要去学 C++ 的窗口 API,也不用碰 Qt 那套复杂的信号槽,前端该怎么写还怎么写,Go 该怎么写还怎么写,中间那根连线 Wails 替你接好了。
1-2 它能做什么
Wails 的定位是”能打硬仗的桌面程序”,不是玩具。下面这些能力在 v2.13.0 里都是现成的:
单文件分发。借助 Go 1.16 之后的资源嵌入能力(//go:embed),前端打包后的静态文件会被编译进最终的二进制里。用户拿到一个 exe 或 app,不需要附带任何资源目录。
Go 方法直接暴露给前端。你在 Go 里写一个公开方法,Wails 启动时用反射扫一遍,自动在前端生成一个同名的 JavaScript 函数,调用它就等于调用 Go。没有 HTTP 接口、没有手写 IPC,前端拿到的是一个返回 Promise 的普通异步函数。
原生系统能力。窗口控制、系统托盘、原生菜单、文件选择框、桌面通知、剪贴板读写——这些桌面程序绕不开的东西,Wails 都封装好了,前端一行调用就能用。
内置开发体验。跑 wails dev 之后,前端改代码热重载,Go 改代码自动重新编译,还有一个内置的 dev server 让你用浏览器 devtools 直接调试界面,体验接近写网页。
双向通信。除了前端调 Go,Go 也能主动推消息给前端(事件系统),比如后台任务跑出进度了,实时送到界面上。
1-3 它不适合做什么
工具没有银弹,先把边界说清楚,免得后面踩坑才发现方向错了:
做不了真正的手机 App。Wails 有实验性的 wails mobile 子命令,但截至 v2.13.0,移动端支持仍不稳定,官方文档把它归在”尝鲜”那一类。要正经做 Android/iOS,还是老老实实上原生或 Flutter。
不是浏览器,别当网页服务器用。Wails 的界面跑在本地 WebView 里,不是远程网页。如果你指望它像服务器那样随便加载外链、跑任意第三方脚本,安全和架构上都不对路。它适合”界面 + 本地逻辑”的桌面程序,不适合做需要复杂远程渲染的云客户端。
非常重的图形计算不在它的强项内。比如你要做专业级 3D 建模、实时视频滤镜这种靠 GPU 猛吃的活,WebView 渲染前端 + Go 算逻辑的组合不是最优解,往往要自己接原生图形接口。
一句话判断:你的程序是”有个界面、主要逻辑在本地跑”的桌面工具,那 Wails 大概率很合适;你要做游戏引擎或云 IDE,那它可能不是首选。
1-4 一个最小示例:前后端怎么连起来
光说概念发飘,看一段能跑的代码。这是 react-ts 模板里最核心的两段——Go 侧和前端侧。
Go 侧,写在 app.go:
package main
import "context"
type App struct {
ctx context.Context
}
func NewApp() *App {
return &App{}
}
func (a *App) Greet(name string) string {
return "你好," + name + "!"
}
前端侧,写在 React 组件里:
import { Greet } from "../wailsjs/go/main/App";
export default function App() {
const handleClick = async () => {
const msg = await Greet("码上学");
alert(msg);
};
return <button onClick={handleClick}>点我打招呼</button>;
}
注意看这条 import:../wailsjs/go/main/App。这个 wailsjs 目录不是你手写的,是 Wails 在编译时根据 Go 的方法自动生成的。“Greet” 这个名字,就是 Go 里那个 Greet 方法。前端调用时,它返回的是一个 Promise——因为跨进程调用本质是异步的。
Tip第一次见
wailsjs目录别慌。它是生成的产物,每次wails dev或wails build都会重新生成,不要手改,也建议加进.gitignore。
把这段对照起来看,Wails 的核心套路就清楚了:Go 写方法 → 启动时自动绑定 → 前端 import 后当普通异步函数调。后面十一章,基本都是在展开这条主线的每一环。
1-5 谁适合用 Wails
如果你符合下面任意一条,Wails 值得你花半天试一把:
- 你本来就会 Go,不想为了写界面去啃 C++ 或 Electron 那套庞大的 JS 生态。
- 你是个前端开发者,想把自己写的网页”固化”成一个能双击打开的桌面程序,又不想背一个上百兆的 Electron 包。
- 你要做的工具是内部用的(运维面板、接口调试器、本地笔记、文件批处理),重点是能跑、好分发,界面漂亮顺手就行。
下一章我们拆开看它内部到底怎么把 Go 和前端接在一起,理解架构之后,后面每章的配置和 API 你都会用得更踏实。
常见误区
以为 Wails 内嵌了一个浏览器。不是。它用的是系统自带的 WebView。好处是包小,代价是不同系统的渲染表现会有细微差别,遇到怪异样式要先想到”这是 WebView 的差异”而不是 Wails 的 bug。
以为前端能直接读本地任意文件、起服务。Wails 的界面运行在受控的本地环境里,前端访问本地资源要走 Wails 提供的资产服务或运行时 API,不是浏览器那套随便 open 本地路径的逻辑。
照着三年前的旧博客抄代码发现编译不过。Wails v1 和 v2 的 API 差别很大,旧文里 wails.Run(&wails.AppConfig{...})、window.backend.App.xxx 这类写法在 v2 已经移除。本教程全部以 v2.13.0 为准,看到旧写法直接跳过。
小结
Wails = Go 业务逻辑 + Web 前端界面 + 系统原生渲染引擎,打包成一个跨平台二进制。它轻量、能打系统能力、开发体验接近写网页,但别指望它做移动端或重型图形程序。最小示例里 wailsjs 自动生成的绑定文件,就是 Go 和前端之间的那座桥——记住它,后面每章都绕着它转。