Go Wails:用Go语言构建现代桌面应用
什么是Wails?
Wails是一个让开发者能够使用Go语言和Web技术(HTML/CSS/JavaScript)构建现代桌面应用程序的框架。它允许你将Go的强大后端能力与灵活的前端技术相结合,创建出跨平台的桌面应用。
项目地址:https://github.com/wailsapp/wails
核心特性
1. 跨平台支持
- Windows
- macOS
- Linux
2. 技术栈
- 后端:纯Go语言
- 前端:任意Web技术(React、Vue、Angular、Svelte等)
- 通信:自动生成的TypeScript绑定,实现前后端无缝通信
3. 现代化功能
- 原生窗口装饰
- 系统托盘支持
- 菜单栏
- 暗黑模式
- 原生对话框
- 文件系统访问
快速开始
安装Wails CLI
text
# 安装wails go install github.com/wailsapp/wails/v2/cmd/wails@latest # 验证安装 wails version
创建第一个Wails应用
text
# 创建新项目 wails init -n MyFirstApp -t react # 进入项目目录 cd MyFirstApp # 安装依赖 npm install # 开发模式运行 wails dev
实例演示:待办事项应用
项目结构
text
todo-app/ ├── main.go # Go后端入口 ├── frontend/ # 前端代码 │ ├── src/ │ │ ├── App.jsx │ │ └── main.jsx │ └── package.json └── wails.json # 项目配置
后端代码 (main.go)
text
package main
import (
"context"
"fmt"
"github.com/wailsapp/wails/v2/pkg/runtime"
)
// TodoItem 结构体
type TodoItem struct {
ID int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
// App 结构体
type App struct {
ctx context.Context
todos []TodoItem
nextID int
}
// NewApp 创建新应用实例
func NewApp() *App {
return &App{
todos: []TodoItem{},
nextID: 1,
}
}
// Startup 应用启动时调用
func (a *App) Startup(ctx context.Context) {
a.ctx = ctx
}
// AddTodo 添加待办事项
func (a *App) AddTodo(title string) TodoItem {
todo := TodoItem{
ID: a.nextID,
Title: title,
Completed: false,
}
a.todos = append(a.todos, todo)
a.nextID++
// 发送事件到前端
runtime.EventsEmit(a.ctx, "todo-added", todo)
return todo
}
// GetTodos 获取所有待办事项
func (a *App) GetTodos() []TodoItem {
return a.todos
}
// ToggleTodo 切换待办事项状态
func (a *App) ToggleTodo(id int) {
for i, todo := range a.todos {
if todo.ID == id {
a.todos[i].Completed = !a.todos[i].Completed
runtime.EventsEmit(a.ctx, "todo-updated", a.todos[i])
break
}
}
}
// DeleteTodo 删除待办事项
func (a *App) DeleteTodo(id int) {
for i, todo := range a.todos {
if todo.ID == id {
a.todos = append(a.todos[:i], a.todos[i+1:]...)
runtime.EventsEmit(a.ctx, "todo-deleted", id)
break
}
}
}
// Greet 示例方法
func (a *App) Greet(name string) string {
return fmt.Sprintf("Hello %s, from Go!", name)
}
前端代码 (App.jsx)
text
import React, { useState, useEffect } from 'react';
import './App.css';
function App() {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState('');
// 从Go后端获取数据
const loadTodos = async () => {
const todos = await window.go.main.App.GetTodos();
setTodos(todos);
};
// 添加待办事项
const handleAddTodo = async () => {
if (newTodo.trim()) {
await window.go.main.App.AddTodo(newTodo);
setNewTodo('');
loadTodos();
}
};
// 切换完成状态
const handleToggleTodo = async (id) => {
await window.go.main.App.ToggleTodo(id);
loadTodos();
};
// 删除待办事项
const handleDeleteTodo = async (id) => {
await window.go.main.App.DeleteTodo(id);
loadTodos();
};
// 监听Go后端事件
useEffect(() => {
const unsubscribe = window.runtime.EventsOn('todo-updated', () => {
loadTodos();
});
return () => {
unsubscribe();
};
}, []);
// 初始加载
useEffect(() => {
loadTodos();
}, []);
return (
<div className="app">
<h1>待办事项应用</h1>
<div className="add-todo">
<input
type="text"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="输入待办事项..."
onKeyPress={(e) => e.key === 'Enter' && handleAddTodo()}
/>
<button onClick={handleAddTodo}>添加</button>
</div>
<div className="todo-list">
{todos.map(todo => (
<div key={todo.id} className="todo-item">
<input
type="checkbox"
checked={todo.completed}
onChange={() => handleToggleTodo(todo.id)}
/>
<span className={todo.completed ? 'completed' : ''}>
{todo.title}
</span>
<button
className="delete-btn"
onClick={() => handleDeleteTodo(todo.id)}
>
删除
</button>
</div>
))}
</div>
</div>
);
}
export default App;
构建和打包
text
# 开发模式 wails dev # 构建应用 wails build # 平台特定构建 wails build -platform windows wails build -platform darwin wails build -platform linux
高级功能示例
1. 系统托盘
text
func (a *App) SetupTray() {
menu := []*menu.MenuItem{
menu.Text("显示应用", nil, func(_ *menu.CallbackData) {
runtime.Show(a.ctx)
}),
menu.Separator(),
menu.Text("退出", nil, func(_ *menu.CallbackData) {
runtime.Quit(a.ctx)
}),
}
runtime.NewTrayMenu(a.ctx, menu)
}
2. 原生对话框
text
func (a *App) OpenFileDialog() string {
file, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
Title: "选择文件",
Filters: []runtime.FileFilter{
{
DisplayName: "文本文件",
Pattern: "*.txt;*.md",
},
},
})
if err != nil {
return ""
}
return file
}
3. 数据库集成
text
import "github.com/jmoiron/sqlx"
import _ "github.com/mattn/go-sqlite3"
type Database struct {
db *sqlx.DB
}
func (d *Database) Init() error {
db, err := sqlx.Open("sqlite3", "data.db")
if err != nil {
return err
}
d.db = db
return d.createTables()
}
优势与适用场景
优势
- 性能优异:Go编译为原生代码,执行效率高
- 内存安全:Go的内存管理机制避免常见的内存错误
- 并发强大:Go的goroutine模型适合处理并发任务
- 部署简单:单个可执行文件,无需运行时环境
- 现代化UI:可使用最新的Web技术构建界面
适用场景
- 需要系统级访问的工具应用
- 数据密集型桌面应用
- 跨平台的企业工具
- 原型开发和MVP验证
- 需要离线功能的桌面应用
学习资源
- 官方文档:https://wails.io/docs/
- 示例项目:https://github.com/wailsapp/wails/tree/master/examples
- 社区模板:多种预配置模板可供选择
- Discord社区:活跃的开发者社区
总结
Wails为Go开发者提供了一个强大的桌面应用开发框架,结合了Go的性能优势和Web技术的灵活性。无论是构建简单的工具应用还是复杂的企业级桌面软件,Wails都能提供完整的解决方案。通过简单的API和现代化的开发体验,它大大降低了桌面应用开发的门槛。
如果你已经熟悉Go语言,并希望将你的技能扩展到桌面应用开发,Wails绝对值得尝试!
wails_20260204162122.zip
类型:压缩文件|已下载:0|下载方式:免费下载
立即下载




还没有评论,来说两句吧...