参与贡献

编辑此文档

翻译文档,或在您的计算机上打开完整项目。

在您选择提交工作成果之前,不会发布任何内容。

枚举

根据 Go 常量自动生成枚举

枚举绑定

Wails v3 绑定生成器会自动检测 Go 常量类型,并生成 TypeScript 枚举或 JavaScript const 对象。无需注册,也无需配置——只需在 Go 中定义类型和常量,其余工作由生成器完成。

快速开始

在 Go 中定义一个具名类型及其常量:

go
type Status string

const (
    StatusActive  Status = "active"
    StatusPending Status = "pending"
    StatusClosed  Status = "closed"
)

在结构体或服务方法中使用该类型:

go
type Ticket struct {
    ID     int    `json:"id"`
    Title  string `json:"title"`
    Status Status `json:"status"`
}

生成绑定:

bash
wails3 generate bindings

生成器的输出会在模型数量旁报告枚举数量:

text
3 Enums, 5 Models

在前端中使用:

javascript
import { Ticket, Status } from './bindings/changeme/models'

const ticket = new Ticket({
    id: 1,
    title: "Bug report",
    status: Status.StatusActive
})

就是这么简单!Go 和 JavaScript/TypeScript 中都会强制使用该枚举类型。

定义枚举

Wails 中的枚举是一个具有基础类型的具名类型,并配有该类型的const 声明。

字符串枚举

go
// Title is a title
type Title string

const (
    // Mister is a title
    Mister Title = "Mr"
    Miss   Title = "Miss"
    Ms     Title = "Ms"
    Mrs    Title = "Mrs"
    Dr     Title = "Dr"
)

生成的 TypeScript:

typescript
/**
 * Title is a title
 */
export enum Title {
    /**
     * The Go zero value for the underlying type of the enum.
     */
    $zero = "",

    /**
     * Mister is a title
     */
    Mister = "Mr",
    Miss = "Miss",
    Ms = "Ms",
    Mrs = "Mrs",
    Dr = "Dr",
}

生成的 JavaScript:

javascript
/**
 * Title is a title
 * @readonly
 * @enum {string}
 */
export const Title = {
    /**
     * The Go zero value for the underlying type of the enum.
     */
    $zero: "",

    /**
     * Mister is a title
     */
    Mister: "Mr",
    Miss: "Miss",
    Ms: "Ms",
    Mrs: "Mrs",
    Dr: "Dr",
};

整数枚举

go
type Priority int

const (
    PriorityLow    Priority = 0
    PriorityMedium Priority = 1
    PriorityHigh   Priority = 2
)

生成的 TypeScript:

typescript
export enum Priority {
    /**
     * The Go zero value for the underlying type of the enum.
     */
    $zero = 0,

    PriorityLow = 0,
    PriorityMedium = 1,
    PriorityHigh = 2,
}

类型别名枚举

Go 类型别名(=)同样有效,但生成的输出略有不同——它会生成类型定义和 const 对象,而不是原生 TypeScript enum:

go
// Age is an integer with some predefined values
type Age = int

const (
    NewBorn    Age = 0
    Teenager   Age = 12
    YoungAdult Age = 18

    // Oh no, some grey hair!
    MiddleAged Age = 50
    Mathusalem Age = 1000 // Unbelievable!
)

生成的 TypeScript:

typescript
/**
 * Age is an integer with some predefined values
 */
export type Age = number;

/**
 * Predefined constants for type Age.
 * @namespace
 */
export const Age = {
    NewBorn: 0,
    Teenager: 12,
    YoungAdult: 18,

    /**
     * Oh no, some grey hair!
     */
    MiddleAged: 50,

    /**
     * Unbelievable!
     */
    Mathusalem: 1000,
};

生成的 JavaScript:

javascript
/**
 * Age is an integer with some predefined values
 * @typedef {number} Age
 */

/**
 * Predefined constants for type Age.
 * @namespace
 */
export const Age = {
    NewBorn: 0,
    Teenager: 12,
    YoungAdult: 18,

    /**
     * Oh no, some grey hair!
     */
    MiddleAged: 50,

    /**
     * Unbelievable!
     */
    Mathusalem: 1000,
};

$zero值

每个具名类型枚举都包含一个特殊的$zero成员,表示其基础类型的Go 零值:

基础类型 $zero值
string ""
int、int8、int16、int32、int64 0
uint、uint8、uint16、uint32、uint64 0
float32、float64 0
bool false

当结构体字段使用枚举类型且未提供值时,构造函数会默认使用$zero:

typescript
export class Person {
    "Title": Title;

    constructor($$source: Partial<Person> = {}) {
        if (!("Title" in $$source)) {
            this["Title"] = Title.$zero;  // defaults to ""
        }
        Object.assign(this, $$source);
    }
}

这可确保生成类时进行类型安全的初始化——枚举字段绝不会是undefined。生成 TypeScript 接口时(使用-i),没有构造函数,字段仍可像往常一样缺省。

在结构体中使用枚举

当结构体字段采用枚举类型时,生成的代码会保留该类型,而不会回退为基本类型:

go
type Person struct {
    Title Title
    Name  string
    Age   Age
}

生成的 TypeScript:

typescript
export class Person {
    "Title": Title;
    "Name": string;
    "Age": Age;

    constructor($$source: Partial<Person> = {}) {
        if (!("Title" in $$source)) {
            this["Title"] = Title.$zero;
        }
        if (!("Name" in $$source)) {
            this["Name"] = "";
        }
        if (!("Age" in $$source)) {
            this["Age"] = 0;
        }

        Object.assign(this, $$source);
    }
}

Title字段的类型是Title,而不是string。这样,IDE 就能为枚举值提供完整的自动补全和类型检查。

来自导入包的枚举

完全支持在其他包中定义的枚举。它们会生成到对应的包目录中:

go
// services/types.go
package services

type Title string

const (
    Mister Title = "Mr"
    Miss   Title = "Miss"
    Ms     Title = "Ms"
)
go
// main.go
package main

import "myapp/services"

func (*GreetService) Greet(name string, title services.Title) string {
    return "Hello " + string(title) + " " + name
}

Title枚举会生成到services模型文件中,并自动解析导入路径:

typescript
// bindings/changeme/services/models.ts
export enum Title {
    $zero = "",
    Mister = "Mr",
    Miss = "Miss",
    Ms = "Ms",
}

枚举方法

可以在 Go 中为枚举类型添加方法。这些方法不会影响绑定生成,但可提供实用的服务端功能:

go
type Title string

func (t Title) String() string {
    return string(t)
}

const (
    Mister Title = "Mr"
    Miss   Title = "Miss"
)

无论该类型是否存在 Go 方法,生成的枚举都完全相同。

注释和文档

生成器会在生成的输出中将 Go 注释保留为 JSDoc:

  • 类型注释会成为枚举的文档注释
  • const 组注释会成为分节符
  • 各个 const 的注释会成为成员文档注释
  • 行内注释会尽可能予以保留

因此,将鼠标悬停在枚举值上时,IDE 会显示相应文档。

支持的基础类型

绑定生成器支持使用以下 Go 基础类型的枚举:

Go 类型 可用作枚举
string 是
int、int8、int16、int32、int64 是
uint、uint8、uint16、uint32、uint64 是
float32、float64 是
byte(uint8) 是
rune(int32) 是
bool 是
complex64、complex128 否

限制

生成枚举时不支持以下内容:

  • 泛型类型 — 类型参数会导致无法检测常量
  • 具有自定义json.Marshaler或encoding.TextMarshaler的类型 — 自定义序列化意味着生成的值可能与运行时行为不一致,因此生成器会跳过这些类型
  • 值无法静态求值或表示的常量 — 常量在其底层类型中必须具有已知且可表示的值。标准iota模式可以正常使用,因为编译器会将它们解析为具体值
  • 复数类型 — complex64和complex128不能作为枚举的底层类型

完整示例

Go:

go
package main

import (
    "github.com/wailsapp/wails/v3/pkg/application"
)

// BackgroundType defines the type of background
type BackgroundType string

const (
    BackgroundSolid    BackgroundType = "solid"
    BackgroundGradient BackgroundType = "gradient"
    BackgroundImage    BackgroundType = "image"
)

type BackgroundConfig struct {
    Type  BackgroundType `json:"type"`
    Value string         `json:"value"`
}

type ThemeService struct{}

func (*ThemeService) GetBackground() BackgroundConfig {
    return BackgroundConfig{
        Type:  BackgroundSolid,
        Value: "#ffffff",
    }
}

func (*ThemeService) SetBackground(config BackgroundConfig) error {
    // Apply background
    return nil
}

func main() {
    app := application.New(application.Options{
        Services: []application.Service{
            application.NewService(&ThemeService{}),
        },
    })
    app.Window.New()
    app.Run()
}

前端(TypeScript):

typescript
import { GetBackground, SetBackground } from './bindings/changeme/themeservice'
import { BackgroundConfig, BackgroundType } from './bindings/changeme/models'

// Get current background
const bg = await GetBackground()

// Check the type using enum values
if (bg.type === BackgroundType.BackgroundSolid) {
    console.log("Solid background:", bg.value)
}

// Set a new background
await SetBackground(new BackgroundConfig({
    type: BackgroundType.BackgroundGradient,
    value: "linear-gradient(to right, #000, #fff)"
}))

前端(JavaScript):

javascript
import { GetBackground, SetBackground } from './bindings/changeme/themeservice'
import { BackgroundConfig, BackgroundType } from './bindings/changeme/models'

// Use enum values for type-safe comparisons
const bg = await GetBackground()

switch (bg.type) {
    case BackgroundType.BackgroundSolid:
        applySolid(bg.value)
        break
    case BackgroundType.BackgroundGradient:
        applyGradient(bg.value)
        break
    case BackgroundType.BackgroundImage:
        applyImage(bg.value)
        break
}

后续步骤

数据模型

结构体、类型映射和模型生成。

了解更多 →

方法绑定

将 Go 方法绑定到前端。

了解更多 →

高级绑定

指令、代码注入和自定义 ID。

了解更多 →

最佳实践

绑定设计模式。

了解更多 →


有疑问?请在Discord中提问,或查看绑定示例。

编辑页面

最后更新: