跳过正文
  1. 文章/
  2. GoLang/
  3. GUI/
  4. Wails/

1、Wails

·3320 字·7 分钟· loading · loading · ·
GoLang GUI Wails
GradyYoung
作者
GradyYoung
Wails - 点击查看当前系列文章
§ 1、Wails 「 当前文章 」

Wails简介
#

Wails 是一个可让您使用 Go 和 Web 技术编写桌面应用的项目。

将它看作为 Go 的快并且轻量的 Electron 替代品。 您可以使用 Go 的灵活性和强大功能,结合丰富的现代前端,轻松的构建应用程序。

后面的笔记将基于 Wails 2.10。

官方文档:https://wails.io/zh-Hans/docs/introduction

功能
#

  • 原生菜单、对话框、主题和半透明
  • Windows、macOS 和 Linux 支持
  • 内置 Svelte、React、Preact、Vue、Lit 和 Vanilla JS 模板
  • 从 JavaScript 轻松调用 Go 方法
  • 自动生成 Go 结构体到 TypeScript 模型
  • Windows 上无需 CGO 或外部 DLL
  • 利用Vite的强大功能进行实时开发模式
  • 强大的 CLI 可轻松创建、构建和打包应用程序
  • 丰富的运行时库
  • 使用 Wails 构建的应用程序符合 Apple 和 Microsoft Store 的要求

快速启动模板
#

Wails 附带许多预配置模板,可帮助您快速启动并运行应用程序。

提供以下框架的模板:Svelte、React、Vue、Preact、Lit 和 Vanilla。

每个模板均提供 JavaScript 和 TypeScript 版本。

原生
#

Wails 使用专门构建的库来处理窗口、菜单、对话框等本机元素,因此您可以构建美观、功能丰富的桌面应用程序。

它不嵌入浏览器,因此运行时占用空间较小。相反,它重用了平台的原生渲染引擎。在 Windows 上,它使用的是基于 Chromium 构建的全新 Microsoft Webview2 库。

Go 和 JavaScript 互操作
#

Wails 会自动将您的 Go 方法提供给 JavaScript,以便您可以从前端通过名称调用它们!它甚至会为您的 Go 方法使用的结构体生成 TypeScript 模型,以便您可以在 Go 和 JavaScript 之间传递相同的数据结构。

运行时库
#

Wails 为 Go 和 JavaScript 提供了一个运行时库,它可以处理现代应用程序需要的很多东西,比如事件、日志记录、对话框等。

实时开发体验
#

自动重新构建
#

当您在“开发”模式下运行您的应用程序时,Wails 会将您的应用程序构建为原生桌面应用程序,但会从磁盘读取您的资源。 它将检测您的 Go 代码的任何更改并自动重新构建和重新启动您的应用程序。

自动重新加载
#

当检测到对您的应用程序资产的更改时,您正在运行的应用程序将“重新加载”,几乎立即反映您的更改

在浏览器中开发您的应用程序
#

如果您更喜欢在浏览器中调试和开发,那么 Wails 可以满足您的需求。 正在运行的应用程序还有一个网络服务器,它将在连接到它的任何浏览器中运行您的应用程序。 当您的资源在磁盘上发生变化时,它会刷新。

可用于生产的原生二进制文件
#

当您准备好最终构建应用程序时,CLI 会将其编译为单个可执行文件,并将所有资源捆绑到其中。

在 Windows 和 MacOS 上,可以创建原生包进行分发。

打包过程中使用的资源(图标、info.plist、清单文件等)是您项目的一部分,可以进行自定义,让您完全掌控应用程序的构建方式。

安装
#

支持的平台
#

  • Windows 10/11 AMD64/ARM64
  • MacOS 10.15+ AMD64 用于开发,MacOS 10.13+ 用于发布
  • MacOS 11.0+ ARM64
  • Linux AMD64/ARM64

依赖
#

Wails 有许多安装前需要的常见依赖项:

  • Go 1.21+(macOS 15+ 需要 Go 1.23.3+)
  • NPM(Node 15+)

安装命令
#

go install github.com/wailsapp/wails/v2/cmd/wails@latest

检查
#

wails doctor

image-20250508160142138

创建项目
#

Wails内置 SvelteReactPreactVueLitVanilla JS 的模板,后面我们使用Vue创建

# 基于 JavaScript
wails init -n myproject -t vue
# 基于 TypeScript
wails init -n myproject -t vue-ts

项目结构
#

├── build/
│   ├── appicon.png
│   ├── darwin/
│   └── windows/
├── frontend/
├── go.mod
├── go.sum
├── main.go
└── wails.json
  • /main.go - 主应用
  • /frontend/ - 前端项目文件
  • /build/ - 项目构建目录
    • /build/appicon.png - 应用程序图标
    • /build/darwin/ - Mac 特定的项目文件
    • /build/windows/ - Windows 特定的项目文件
  • /wails.json - 项目配置
  • /go.mod - Go module 文件
  • /go.sum - Go module 校验文件

frontend 目录没有特定于 Wails 的内容,可以是您选择的任何前端项目。

build 目录在构建过程中使用。 这些文件可以修改以自定义您的构建。 如果从 build 目录中删除文件,将重新生成默认版本。

go.mod 中的默认模块名称是“changeme”。 您应该将其更改为更合适的内容。

运行项目
#

您可以通过从项目目录运行 wails dev 在开发模式下运行您的应用程序。 这将执行以下操作:

  • 构建您的应用程序并运行它
  • 将您的 Go 代码绑定到前端,以便可以从 JavaScript 调用它
  • 使用Vite的强大功能,将监视您的 Go 文件中的修改并在更改时重新构建/重新运行
  • 启动一个网络服务器通过浏览器为您的应用程序提供服务。 这使您可以使用自己喜欢的浏览器扩展。 你甚至可以从控制台调用你的 Go 代码。

工作原理
#

Wails 应用程序是一个带有一个 webkit 前端的标准的 Go 应用程序。 应用程序的 Go 部分由应用程序代码和一个运行时库组成, 该库提供了许多有用的操作,例如控制应用程序窗口。 前端是一个 webkit 窗口,将显示前端资源。 前端还可以使用运行时库的 JavaScript 版本。 最后,可以将 Go 方法绑定到前端,这些将显示为可以调用的 JavaScript 方法,就像它们是原生 JavaScript 方法一样。

img

主应用程序
#

主应用程序由对 wails.Run() 的调用组成。 它接受描述应用程序窗口大小、窗口标题、要使用的资源等应用程序配置。 基本应用程序可能如下所示:

package main

import (
	"context"
	"embed"
	"fmt"

	"github.com/wailsapp/wails/v2"
	"github.com/wailsapp/wails/v2/pkg/options"
	"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)

// App struct
type App struct {
	ctx context.Context
}

// NewApp creates a new App application struct
func NewApp() *App {
	return &App{}
}

// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

// Greet returns a greeting for the given name
func (a *App) Greet(name string) string {
	return fmt.Sprintf("Hello %s, It's show time!", name)
}

//go:embed all:frontend/dist
var assets embed.FS

func main() {
	// Create an instance of the app structure
	app := NewApp()

	// Create application with options
	err := wails.Run(&options.App{
		Title:  "wails-demo",
		Width:  1024,
		Height: 768,
		AssetServer: &assetserver.Options{
			Assets: assets,
		},
		BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
		OnStartup:        app.startup,
		Bind: []interface{}{
			app,
		},
	})

	if err != nil {
		println("Error:", err.Error())
	}
}
  • Title - 应该出现在窗口标题栏中的文本
  • Width & Height - 窗口的尺寸
  • Assets - 应用程序的前端资产
  • OnStartup - 创建窗口并即将开始加载前端资源时的回调
  • OnShutdown - 应用程序即将退出时的回调
  • Bind - 我们希望向前端暴露的一部分结构体实例

资产
#

Assets 选项是必须的,因为您不能拥有没有前端资产的 Wails 应用程序。 这些资产可以是您希望在 Web 应用程序中找到的任何文件 - html、js、css、svg、png 等。 不需要生成资源包 - 普通文件即可。 当应用程序启动时,它将尝试从您的资产中加载 index.html,并且那时起前端基本上将作为浏览器工作。 值得注意的是 embed.FS 对文件所在的位置没有要求。 嵌入路径很可能使用了相对于您的主应用程序代码的嵌套目录,例如 frontend/dist

//go:embed all:frontend/dist
var assets embed.FS

启动时,Wails 将遍历嵌入的文件,寻找包含的 index.html。 所有其他资源将相对于该目录加载。

由于可用于生产的二进制文件使用包含在 embed.FS 中的文件,因此应用程序不需要附带任何外部文件。

在开发模式下使用 wails dev 命令,资产从磁盘加载,任何更改都会导致“实时重新加载”。 资产的位置将从 embed.FS 推断。

应用程序生命周期回调
#

  • 在即将加载前端 index.html 之前,会对应用启动回调OnStartup)中提供的函数进行调用。
  • 一个标准的 Go context 被传递给这个方法。 调用运行时需要此 context ,因此标准模式是在此方法中保存对它的引用。
  • 还有一个前端 Dom 加载完成回调OnDomReady),相当于 JavaScript 中的body onload事件。
  • 还可以通过设置应用关闭前回调OnBeforeClose)选项来控制窗口关闭(或应用程序退出)事件。
  • 在应用程序关闭之前,以同样的方式调用应用退出回调OnShutdown)。

方法绑定
#

Bind 选项是 Wails 应用程序中最重要的参数选项之一。 它指定向前端暴露哪些结构体方法。

当应用程序启动时,它会检查 Bind 字段中列出的结构体实例, 确定哪些方法是公开的(以大写字母开头),并生成前端可以调用的这些方法的 JavaScript 版本。

您可以绑定任意数量的结构体。 只需确保创建它的实例并将其传递给 Bind

当您运行 wails dev(或 wails generate module)时,将生成一个前端模块,其中包含以下内容:

  • 所有绑定方法的 JavaScript 绑定
  • 所有绑定方法的 TypeScript 声明
  • 绑定方法用作输入或输出的所有 Go 结构的 TypeScript 声明

前端
#

前端是由 webkit 渲染的文件集合。 这就合二为一的浏览器和网络服务器。 您可以使用的框架或库1几乎没有限制。 前端和 Go 代码之间的主要交互点是:

  • 调用绑定的 Go 方法
  • 调用运行时方法

调用绑定的 Go 方法
#

当您使用 wails dev 运行应用程序时,它将自动在名为 wailsjs/go 的目录中为您的结构体生成 JavaScript 绑定(您也可以通过运行 wails generate module 来执行此操作)。 生成的文件反映了应用程序中的包名称。

export function Greet(arg1: string): Promise<string>;

生成的方法返回一个 Promise 成功的调用将导致 Go 调用的第一个返回值被传递给 resolve 处理程序。

不成功的调用是当 Go 方法的第二个返回值具有错误类型时,将错误实例传递回调用者。 这通过 reject 处理程序传回的。

所有数据类型都在 Go 和 JavaScript 之间正确转换。 包括结构体。 如果您从 Go 调用返回一个结构体,它将作为 JavaScript 类返回到您的前端。

**注意:**结构体字段必须具有有效的 json 标签,以包含在生成的 TypeScript 中。

调用运行时方法
#

JavaScript 运行时位于window.runtime并包含许多方法来执行各种任务,例如发出事件或执行日志记录操作:

window.runtime.EventsEmit("my-event", 1);
Wails - 点击查看当前系列文章
§ 1、Wails 「 当前文章 」