Go 的编译速度已经不算慢,但在日常开发里,最打断节奏的往往还是那套重复动作:改代码、回到终端、Ctrl+C 停掉进程、再执行 go run main.go。对于 Web 服务、接口调试或模板联调来说,这种频繁重启带来的成本并不高,却足够琐碎,时间一长就会明显拖慢开发体验。
热更新工具解决的正是这类问题:监听文件变化,在保存后自动编译并重启程序。有的工具偏向开箱即用,有的强调灵活配置,也有些更适合多语言项目或多服务场景。下面按实际使用差异来梳理几款常见方案,方便你判断哪一类更适合当前项目。
Air:目前最稳妥的主流选择
如果只选一个工具作为 Go 项目的默认热更新方案,Air 通常是最容易推荐的那个。它在 Go 社区使用广泛,GitHub 星标超过 23k,功能完整,而且仍在持续维护。

Air 的核心思路很直接:监控项目文件变化,自动执行构建并重启程序。相比一些更轻量的方案,它的优势在于可配置项足够细,既能自定义构建命令和启动参数,也能精确控制哪些目录和文件需要监听。实际开发中,这一点很重要,因为很多项目并不希望把 vendor、tmp、静态资源目录都纳入监听范围。
安装命令如下:
go install github.com/air-verse/air@latest
进入项目根目录后执行 air init,会生成默认配置文件 .air.toml。一个常见配置如下:
[build]
cmd = "go build -o ./tmp/main ."
entrypoint = ["./tmp/main"]
include_ext = ["go", "tpl", "tmpl", "html"]
exclude_dir = ["assets", "tmp", "vendor"]
delay = 1000
这段配置表达了几个关键信息:只监听 go、tpl、tmpl、html 等文件;排除 assets、tmp、vendor 目录;文件改动后延迟 1 秒再执行构建,避免连续保存时频繁触发。编译产物会输出到 tmp 目录,再由 Air 自动拉起。
Air 还有两个很实用的细节。第一是日志输出做得比较清楚,不同级别的信息用颜色区分,排查编译错误时更直观。第二是编译失败时可以保持旧版本继续运行,这对本地接口联调尤其友好,不会因为一次写错语法就把整个服务直接打断。
如果你是第一次给 Go 项目接入热更新,或者希望工具本身别太折腾,Air 基本是优先级最高的选择。
Reflex:适合多语言项目的通用监控方案
Reflex 并不是只为 Go 设计的工具,它本质上是一个通用的文件监控器。也正因为这一点,它在包含多种语言或多种构建任务的项目里会更有优势。
基本用法如下:
go install github.com/cespare/reflex@latest
reflex -r '.go$' -s -- go run main.go
这里的 -r 使用正则表达式匹配文件,-s 表示将目标进程作为服务启动,在文件变化时自动重启。对于只监听 Go 文件并重跑服务的场景,这条命令已经够用。
Reflex 的真正价值在于灵活。比如你的项目同时有 Go 后端和前端资源构建任务,就可以把不同类型的文件变化交给不同命令处理,而不需要为每一块都单独找工具:
# Rebuild SCSS when it changes
-r '.scss$' -- sass {} `basename {} .scss`.css
# Restart server when Go code changes
-sr '.go$' -- go run main.go
这类配置很适合“一个仓库里有多个运行任务”的开发模式。比如保存 .scss 文件时只重建样式,保存 .go 文件时才重启后端服务。相比只面向 Go 的热更新工具,Reflex 更像是一个统一调度器,能把多语言项目的本地开发流程收拢到一起。
如果你的项目边界比较单一,Reflex 未必比 Air 更省心;但只要仓库里同时有 Go、Node.js、样式编译或其他脚本任务,它的通用性就会立刻体现出来。
另外三款工具怎么用,适合什么场景
CompileDaemon:只做监控与触发,适合自定义流程
CompileDaemon 走的是极简路线。它主要负责监听文件变化并触发编译或命令执行,本身不强调一整套完整的开发工作流,因此更适合已经有自己启动流程的项目。

go install github.com/githubnemo/CompileDaemon@latest
CompileDaemon -command="./your-app"
-command 用来指定编译完成后执行的命令。它的灵活点在于,你可以把数据库迁移、预处理脚本、容器内启动命令等逻辑放到自己的流程里,再让 CompileDaemon 负责后续监控。对 Docker 容器开发来说,这种做法也比较常见。不过需要注意,这个项目长期没有发布新版本,作为新项目默认方案并不算理想。
Fresh:想尽快跑起来时的轻量选择
Fresh 是较早一批 Go 热更新工具,主打零配置使用。对不想先研究配置文件的人来说,它的门槛确实很低。
go install github.com/gravityblast/fresh@latest
fresh
安装完成后,在项目目录直接执行 fresh 就可以开始监听当前目录下的 Go 文件变化,保存后自动重新编译并运行。它适合小型项目、临时原型或者演示代码。代价也很明显:如果你需要排除特定目录、自定义构建命令、细分监听规则,Fresh 的空间就比较有限。这种情况下,通常还是会转向 Air。
Realize:适合多服务统一管理,但不建议新项目入场
Realize 的定位和前面几款不太一样。它不只是热更新工具,更像一个面向开发阶段的项目工作台,除了监听重启,还包含日志管理、自动测试、多项目组织等能力。
它比较有代表性的能力,是在一个配置文件里统一管理多个服务:
projects:
- name: user-service
path: ./services/user
commands:
run: go run main.go
- name: order-service
path: ./services/order
commands:
run: go run main.go
对于微服务项目,这种配置方式能把多个服务的运行命令、路径和监听规则集中起来。Realize 还提供 Web 界面,可以在浏览器中查看项目状态和日志输出。问题也同样明确:近几年没有更新,维护状态不适合新项目长期依赖。把它当作思路参考可以,直接作为主力工具则需要谨慎。
怎么选:按项目类型做判断更直接
这几款工具看起来都在做“保存后自动重启”,但使用边界并不一样。与其逐个比较参数,不如先看项目本身是什么类型。
如果你是新手,或者只想尽快稳定用起来,优先考虑 Air。它的文档、社区和维护状态都更可靠,配置也不算复杂,适合作为默认答案。
如果你的仓库里不只有 Go,比如后端是 Go,前端或构建脚本还有 Node.js、SCSS 等内容,Reflex 往往更顺手。因为它不是把“Go 热更新”做好,而是把“文件变化后执行什么命令”这件事做得足够通用。
如果你在容器环境里开发,Air 和 Reflex 都是更现实的选择。两者都更容易嵌入现有流程,也比一些长期停更的工具更适合持续使用。
如果你只是在做很小的实验项目,Fresh 仍然有价值,尤其是在你不想写配置的时候。但只要项目规模一上来,配置能力不足很快就会暴露出来。
至于 CompileDaemon 和 Realize,前者更像给有自定义流程需求的人准备的基础组件,后者适合拿来理解多项目管理的思路。二者都不是今天新项目的首选。
结语:热更新不是必需品,但很容易变成高频工具
热更新工具看起来只是把“重启程序”自动化,但它真正带来的价值,是把开发过程里的机械操作尽量拿掉。保存代码后立即看到结果,这种反馈速度对接口调试、页面联调和问题定位都很直接。
如果你现在还在频繁手动执行 go run main.go,最值得尝试的起点其实很明确:单项目先上 Air,多语言仓库再看 Reflex。工具本身不复杂,但选对之后,日常开发节奏会顺很多。









