go实时重载air

Go Air 详细讲解

Air 是一个用于 Go 应用程序的实时重载工具,可以在代码更改时自动重建和重启应用程序,极大提高开发效率。

1. 安装

方式一:使用 Go 安装

1
go install github.com/cosmtrek/air@latest

方式二:直接下载二进制文件

1
2
3
4
5
6
7
8
# Linux
curl -fLo air https://git.io/linux_air

# macOS
curl -fLo air https://git.io/darwin_air

# Windows
curl -fLo air.exe https://git.io/windows_air

方式三:使用包管理器

1
2
3
4
5
6
7
8
# macOS with Homebrew
brew install air

# Windows with Scoop
scoop install air

# Arch Linux with yay
yay -S air

2. 基本使用

快速开始

1
2
3
4
5
6
7
8
# 在项目根目录执行
air

# 指定配置文件
air -c .air.toml

# 初始化配置文件
air init

项目结构示例

1
2
3
4
5
6
myproject/
├── main.go
├── go.mod
├── .air.toml # Air 配置文件
└── cmd/
└── server.go

3. 配置文件详解

初始化默认配置

1
air init

这会生成一个 .air.toml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# .air.toml
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
# 只在当前目录运行,不递归子目录
include_ext = ["go", "tpl", "tmpl", "html"]
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
include_dir = []
exclude_file = []

# 监视这些文件扩展名的文件
include_ext = ["go", "tpl", "tmpl", "html"]

# 忽略这些目录
exclude_dir = ["assets", "tmp", "vendor", "testdata", ".git"]

# 监视这些目录(默认为 ".")
include_dir = []

# 排除文件
exclude_file = []

# 构建命令
cmd = "go build -o ./tmp/main ."

# 构建的二进制文件位置
bin = "tmp/main"

# 自定义二进制输出名称
full_bin = "./tmp/main"

# 监听文件更改时运行的命令
args_bin = []

# 是否显示日志
log = "air.log"

# 是否在运行前停止旧的二进制文件
stop_on_root = false

# 发送中断信号的超时时间(秒)
send_interrupt = false
interrupt_timeout = 5
kill_delay = 0

# 延迟运行(秒)
delay = 1000

[log]
# 是否显示日志时间
time = false

[color]
# 自定义颜色
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
# 退出时是否删除临时目录
clean_on_exit = true

自定义配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Air的配置文件,格式为TOML

# 工作目录
root = "."
# air在运行时存储临时文件的目录
tmp_dir = "tmp" # 改为相对路径,便于移植

[build]
# 每次构建前要运行的命令数组
pre_cmd = ["go mod tidy"] # 添加依赖整理
# 普通的shell命令
cmd = "go build -o ./tem/main ./cmd/main.go"
# ^C后要运行的命令数组
post_cmd = []
# 从`cmd`得到的二进制文件
bin = "tem/main"
# 自定义二进制文件运行命令
# full_bin = "ENV=dev ./tem/main serve --config=config.yaml"
# 运行二进制文件时的参数
args_bin = [] # 可以添加如: ["serve", "--port=8080"]
# 监视这些文件名扩展名
include_ext = ["go", "tpl", "tmpl", "html", "yaml", "yml"] # 添加配置文件类型
# 忽略这些文件名扩展名或目录
exclude_dir = [
"assets",
"tmp",
"vendor",
"frontend/node_modules",
".git",
"_output", # 添加输出目录
"logs" # 添加日志目录
]
# 监视这些目录
include_dir = ["cmd", "internal", "pkg", "configs"] # 明确指定监视目录
# 监视这些文件
include_file = []
# 排除文件
exclude_file = []
# 排除特定的正则表达式
exclude_regex = ["_test\\.go", "_mock\\.go"] # 添加mock文件排除
# 排除未更改的文件
exclude_unchanged = true
# 跟随目录的符号链接
follow_symlink = true
# 此日志文件放置在你的tmp_dir中
log = "air.log"
# 轮询文件以检测更改
poll = false
# 轮询间隔
poll_interval = 500
# 构建延迟,避免频繁构建
delay = 1000 # 增加到1秒,减少频繁构建
# 当构建错误发生时停止运行旧的二进制文件
stop_on_error = true
# 发送中断信号之前杀死进程
send_interrupt = true # 改为true,确保进程正确退出
# 发送中断信号后的延迟
kill_delay = 1000000000 # 改为1秒 (1,000,000,000 纳秒 = 1秒)
# 是否重新运行二进制文件
rerun = true # 改为true,构建成功后自动重新运行
# 每次执行后的延迟
rerun_delay = 1000 # 改为1000ms

[log]
# 显示日志时间
time = true # 改为true,便于调试
# 仅显示主日志
main_only = false

[color]
# 自定义每个部分的颜色
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
# 退出时删除tmp目录
clean_on_exit = true

[screen]
# 重建时清屏
clear_on_rebuild = true
# 保持滚动
keep_scroll = true

# 启用浏览器的实时重载
[proxy]
enabled = true
proxy_port = 8090
app_port = 8080

4. 实际项目配置示例

Web 服务器项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# .air.toml
root = "."
tmp_dir = "tmp"

[build]
cmd = "go build -o ./tmp/main ./cmd/server"
bin = "tmp/main"
full_bin = "./tmp/main server --config=config.yaml"
include_ext = ["go", "yaml", "yml", "json"]
exclude_dir = ["tmp", "vendor", "testdata", "logs", ".git"]
include_dir = ["cmd", "internal", "pkg", "configs"]
log = "air.log"
delay = 1000
stop_on_root = false
send_interrupt = true

[log]
time = true

[color]
main = "blue"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
clean_on_exit = false # 保留日志文件

微服务项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# .air.toml
root = "."
tmp_dir = "tmp"

[build]
cmd = "go build -ldflags '-s -w' -o ./tmp/main ./cmd/user-service"
bin = "tmp/main"
full_bin = "./tmp/main --env=dev"
include_ext = ["go", "proto", "yaml"]
exclude_dir = ["tmp", "vendor", "testdata", "dist", ".git"]
include_dir = ["cmd", "internal", "pkg", "api", "config"]
log = "air.log"
delay = 1500
stop_on_root = true

[log]
time = true

[color]
main = "green"
watcher = "blue"
build = "magenta"
runner = "yellow"

5. 集成到开发工作流

与 Makefile 集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Makefile
.PHONY: dev build test

dev:
air -c .air.toml

build:
go build -o bin/server ./cmd/server

test:
go test ./...

run:
go run ./cmd/server

clean:
rm -rf tmp bin

与 Docker 集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Dockerfile.dev
FROM golang:1.19-alpine

WORKDIR /app

# 安装 air
RUN go install github.com/cosmtrek/air@latest

# 复制配置文件
COPY .air.toml ./
COPY go.mod go.sum ./
RUN go mod download

# 复制源代码
COPY . .

# 启动 air
CMD ["air", "-c", ".air.toml"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# docker-compose.dev.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "8080:8080"
volumes:
- .:/app
- /app/tmp
environment:
- GO_ENV=development

6. 高级配置技巧

环境特定配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# .air.toml
root = "."

[build]
# 基础配置
cmd = "go build -o ./tmp/main ."
bin = "tmp/main"

# 开发环境特定配置
[build.dev]
full_bin = "./tmp/main --env=dev --debug=true"
args_bin = ["--port=3000"]

# 测试环境特定配置
[build.test]
full_bin = "./tmp/main --env=test"
args_bin = ["--port=8080"]

[log]
time = true

[color]
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

多命令支持

1
2
3
4
5
6
7
8
9
10
# 运行多个命令
[build]
cmd = "go generate && go build -o ./tmp/main ."
bin = "tmp/main"
full_bin = "./tmp/main"

# 或者使用数组形式
[build]
cmd = ["go", "generate", "&&", "go", "build", "-o", "./tmp/main", "."]
bin = "tmp/main"

7. 常见问题解决

go版本问题

air最新版需要go版本>=1.25

1
2
3
4
5
6
7
8
# 启用校验和验证(推荐)
export GOSUMDB=on
# 或者使用国内的代理(如果网络访问有问题)
export GOSUMDB=sum.golang.org
export GOPROXY=https://goproxy.cn,direct

# 重新安装
go install github.com/air-verse/air@latest

权限问题

1
2
3
4
5
6
# 给生成的二进制文件执行权限
chmod +x tmp/main

# 或者在配置中设置
[build]
cmd = "go build -o ./tmp/main . && chmod +x ./tmp/main"

端口占用问题

1
2
3
4
5
[build]
# 确保旧进程被正确终止
send_interrupt = true
interrupt_timeout = 5
kill_delay = 1000

处理静态文件

1
2
3
4
[build]
# 包含模板和静态文件
include_ext = ["go", "html", "tpl", "tmpl", "css", "js"]
exclude_dir = ["tmp", "vendor", "testdata", "dist"]

8. 性能优化配置

最小化监视范围

1
2
3
4
5
6
7
8
9
10
11
[build]
# 只监视必要的目录
include_dir = ["cmd", "internal", "pkg"]
exclude_dir = [
"tmp", "vendor", "testdata",
"node_modules", "dist", ".git",
"docs", "migrations"
]

# 减少延迟
delay = 500 # 毫秒

优化构建命令

1
2
3
4
5
6
7
[build]
# 使用缓存和优化标志
cmd = "go build -tags=jsoniter -o ./tmp/main ."
bin = "tmp/main"

# 或者使用更快的构建工具
# cmd = "goreleaser build --skip=validate --single-target"

9. 与其他工具集成

与 Reflex 比较

1
2
3
# Reflex 的类似功能
go get github.com/cespare/reflex
reflex -r '\.go$' -s -- go run main.go

与 Nodemon 比较

1
2
3
# 对于 Go 项目,Air 比 Nodemon 更合适
# Nodemon 主要用于 Node.js
nodemon --exec go run main.go --ext go

10. 最佳实践

  1. 版本控制:将 .air.toml 加入版本控制
  2. 环境配置:为不同环境创建不同的配置文件
  3. 性能优化:合理设置监视目录,避免不必要的文件监视
  4. 错误处理:配置适当的超时和中断设置
  5. 日志管理:在生产环境中禁用 Air,仅用于开发

示例项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
myapp/
├── .air.toml
├── .air.prod.toml
├── Makefile
├── Dockerfile
├── Dockerfile.dev
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ └── app/
├── pkg/
│ └── utils/
└── go.mod

Air 是 Go 开发中非常有用的工具,可以显著提高开发效率,特别是在需要频繁修改和测试的 Web 开发场景中。

[up主专用,视频内嵌代码贴在这]