air-go
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAir — Go Hot Reload
Air — Go 应用热重载
Air watches Go source files and
rebuilds/restarts your app on changes. Essential for web server development
where you want sub-second feedback.
Air 会监听Go源文件,在文件变更时重新构建/重启你的应用。对于需要亚秒级反馈的Web服务器开发来说,它是必不可少的工具。
Install
安装
bash
go install github.com/air-verse/air@latestbash
go install github.com/air-verse/air@latestBasic usage
基础用法
Run in your project root. With no config, it watches files,
rebuilds, and restarts. For anything non-trivial, use a .
air.go.air.toml在项目根目录运行命令。无配置情况下,它会监听文件,进行重新构建并重启应用。对于非简单项目,请使用配置文件。
air.go.air.toml.air.toml
.air.toml
toml
root = "."
tmp_dir = "tmp"
[build]
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ."
delay = 500
exclude_dir = ["tmp", "k8s", "cmd", "node_modules", "vendor"]
exclude_regex = ["_test\\.go$"]
include_ext = ["go", "html", "css", "js", "yml", "yaml", "toml"]
kill_delay = "1s"
send_interrupt = true
stop_on_error = true
[misc]
clean_on_exit = truetoml
root = "."
tmp_dir = "tmp"
[build]
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ."
delay = 500
exclude_dir = ["tmp", "k8s", "cmd", "node_modules", "vendor"]
exclude_regex = ["_test\\.go$"]
include_ext = ["go", "html", "css", "js", "yml", "yaml", "toml"]
kill_delay = "1s"
send_interrupt = true
stop_on_error = true
[misc]
clean_on_exit = trueKey settings explained
关键配置说明
| Setting | What it does | Why it matters |
|---|---|---|
| Milliseconds to wait after a file change before rebuilding | Prevents rapid-fire rebuilds when saving multiple files |
| Time to wait after killing the old process before starting the new one | Critical for SQLite/file locks — the old process needs time to release resources |
| Send SIGINT before SIGKILL | Allows graceful shutdown (flush writes, close DB connections) |
| Don't restart on build errors | Prevents crash loops when you have a syntax error |
| File extensions to watch | Add |
| Directories to ignore | Exclude test fixtures, k8s manifests, vendored deps |
| File patterns to ignore | Skip test files to avoid rebuilding when only tests change |
| Remove tmp dir on exit | Prevents stale binaries from confusing the next run |
| 配置项 | 功能说明 | 重要性 |
|---|---|---|
| 文件变更后等待重新构建的毫秒数 | 避免保存多个文件时触发频繁的重新构建 |
| 终止旧进程后等待启动新进程的时间 | 对SQLite/文件锁至关重要——旧进程需要时间释放资源 |
| 在发送SIGKILL前先发送SIGINT | 允许优雅关闭(刷新写入、关闭数据库连接) |
| 构建出错时不再重启应用 | 避免出现语法错误时陷入崩溃循环 |
| 要监听的文件扩展名 | 添加 |
| 要忽略的目录 | 排除测试 fixtures、k8s清单、第三方依赖包 |
| 要忽略的文件模式 | 跳过测试文件,避免仅测试文件变更时触发重新构建 |
| 退出时删除临时目录 | 防止陈旧二进制文件干扰下次运行 |
Makefile integration
与Makefile集成
makefile
.PHONY: dev dev-email dev-cleanmakefile
.PHONY: dev dev-email dev-cleanDev: console output, fresh state
Dev: 控制台输出,全新状态
dev: dev-clean
air
dev: dev-clean
air
Dev: real emails, LAN-accessible for mobile testing
Dev: 发送真实邮件,支持LAN访问用于移动端测试
dev-email: dev-clean
$(call setup_env, .env.prod)
SMTP_HOST=smtp.example.com
BASE_URL=http://$(LAN_IP):8080
air
BASE_URL=http://$(LAN_IP):8080
air
dev-clean:
@rm -f app.db app.db-shm app.db-wal tmp/main
@-lsof -ti :8080 | xargs kill -9 2>/dev/null || true
The `dev-clean` target is important — it kills anything on the port and removes
stale DB files before starting fresh.dev-email: dev-clean
$(call setup_env, .env.prod)
SMTP_HOST=smtp.example.com
BASE_URL=http://$(LAN_IP):8080
air
BASE_URL=http://$(LAN_IP):8080
air
dev-clean:
@rm -f app.db app.db-shm app.db-wal tmp/main
@-lsof -ti :8080 | xargs kill -9 2>/dev/null || true
`dev-clean`目标非常重要——它会杀死端口上的所有进程,并在重新启动前删除陈旧的数据库文件。Passing environment variables
传递环境变量
Air inherits the parent shell's environment. Set env vars inline before :
airbash
undefinedAir会继承父shell的环境变量。在命令前直接设置环境变量:
airbash
undefinedInline
直接设置
PORT=3000 DEBUG=true air
PORT=3000 DEBUG=true air
From .env file in Makefile
在Makefile中从.env文件读取
$(call setup_env, .env.dev)
air
Do NOT put env vars in `.air.toml` — it doesn't support that. Environment is
always from the shell.$(call setup_env, .env.dev)
air
不要将环境变量放在`.air.toml`中——它不支持这种方式。环境变量始终来自shell。Common issues and fixes
常见问题与解决方法
"address already in use"
「地址已被占用」
The previous process didn't die. Fix:
bash
lsof -ti :8080 | xargs kill -9Or add to target as shown above.
dev-clean之前的进程未终止。解决方法:
bash
lsof -ti :8080 | xargs kill -9或者如上文所示,将该命令添加到目标中。
dev-clean"database is locked" (SQLite)
「数据库已锁定」(SQLite)
Air kills the old process and starts the new one, but SQLite WAL files can
linger. Fix with these settings:
.air.tomltoml
[build]
kill_delay = "1s" # Give old process time to release the lock
send_interrupt = true # Graceful shutdown via SIGINT
pre_cmd = ["rm -f app.db-shm app.db-wal"] # Clean stale lock filesIf using an in-memory DB or ephemeral dev DB, just delete it on each rebuild:
toml
[build]
pre_cmd = ["rm -f app.db app.db-shm app.db-wal"]Air会终止旧进程并启动新进程,但SQLite的WAL文件可能会残留。通过以下配置解决:
.air.tomltoml
[build]
kill_delay = "1s" # 给旧进程时间释放锁
send_interrupt = true # 通过SIGINT实现优雅关闭
pre_cmd = ["rm -f app.db-shm app.db-wal"] # 清理陈旧锁文件如果使用内存数据库或临时开发数据库,只需在每次重新构建时删除它:
toml
[build]
pre_cmd = ["rm -f app.db app.db-shm app.db-wal"]"too many open files" on large projects
大型项目中出现「打开文件过多」
Air's file watcher can hit OS limits. Exclude unnecessary directories:
toml
[build]
exclude_dir = ["tmp", "vendor", "node_modules", ".git", "k8s", "docs"]Air的文件监视器可能会达到操作系统限制。排除不必要的目录:
toml
[build]
exclude_dir = ["tmp", "vendor", "node_modules", ".git", "k8s", "docs"]Air exits immediately in background/CI
在后台/CI中Air立即退出
Air is a foreground tool — it watches stdin for . In scripts or CI, use
instead. Air is for interactive development only.
Ctrl+Cgo run .Air是一个前台工具——它会监听标准输入以等待。在脚本或CI中,请改用。Air仅适用于交互式开发。
Ctrl+Cgo run .Changes not detected
未检测到变更
Check that your file extension is in and the directory isn't in
. Air only watches extensions you explicitly list.
include_extexclude_dir检查你的文件扩展名是否在中,且所在目录未被列入。Air仅会监听你明确列出的扩展名。
include_extexclude_dirWatching non-Go files
监听非Go文件
To rebuild on HTML/CSS/JS changes (useful for apps that serve static files):
toml
[build]
include_ext = ["go", "html", "css", "js"]Air will rebuild the Go binary even when only frontend files change. This is
fine — Go builds are fast and the restart picks up the new static files.
要在HTML/CSS/JS变更时触发重新构建(适用于提供静态文件的应用):
toml
[build]
include_ext = ["go", "html", "css", "js"]即使只有前端文件变更,Air也会重新构建Go二进制文件。这没问题——Go构建速度很快,重启后会加载新的静态文件。
Multi-binary projects
多二进制文件项目
If your project has multiple binaries (, ), point
at the one you want:
cmd/servercmd/workercmdtoml
[build]
cmd = "go build -o ./tmp/server ./cmd/server"
bin = "./tmp/server"Run a second air instance in another terminal for the worker if needed, with a
separate config:
bash
air -c .air.worker.toml如果你的项目有多个二进制文件(如、),将指向你需要的那个:
cmd/servercmd/workercmdtoml
[build]
cmd = "go build -o ./tmp/server ./cmd/server"
bin = "./tmp/server"如果需要,在另一个终端中运行第二个Air实例来处理worker,使用单独的配置:
bash
air -c .air.worker.toml