Revel调试需按错误类型分路径:启动失败是端口占用,请求500需开-v日志并检查PanicFilter,前端静默失败多因CORS或HTTPS混合内容,异步panic须手动recover。

Revel 框架报错不能靠“重启看会不会好”,得先分清是启动阶段卡死、请求进来就 500,还是前端发请求后服务端静默失败——每种对应完全不同的调试路径。
启动失败:Failed to start reverse proxy: listen tcp:9000: address already in use
这是最常被当成“Revel 报错”的假问题。它根本不是框架 bug,而是端口被占了。
- 用
lsof -n -i4TCP:9000 | grep LISTEN查谁在用(macOS/Linux);Windows 用netstat -ano | findstr :9000 - 别硬改代码去换端口,直接改配置文件:
config/app.conf里加一行http.port = 8888 - 临时调试可用命令行:
revel run myapp dev 8888,但这个不会写入配置,下次还得输 - 注意:如果用了 Nginx 或 Caddy 做反代,
proxy_pass地址必须和revel run实际监听的-addr+-p完全一致,否则会 502
请求 500:控制台只打印 panic,没堆栈,或堆栈停在拦截器里
Revel 的错误捕获默认不输出完整调用链,尤其在自定义拦截器中 panic 时,容易漏掉原始错误点。
- 启动时加
-v参数:revel run myapp dev -v,强制输出详细日志 - 检查
app/init.go中是否误删了revel.InterceptMethod(revel.PanicFilter, revel.BEFORE)—— 这个是兜底 panic 捕获器,删了就只剩裸 panic - 若错误发生在模板渲染阶段(比如
{{.User.Name}}但.User是 nil),Revel 默认只报template: ...: nil pointer evaluating interface {}.Name,需手动在 controller 里加空值判断,不能依赖模板容错 - 自定义拦截器中若调用
c.RenderError(),要确保返回的是revel.Result,否则可能触发空指针 panic
前端请求失败但后端无日志:CORS、HTTPS 混合内容、预检失败
这类不是 Revel 报错,但开发者常以为是框架没收到请求——其实请求压根没发到服务端。
- 打开浏览器 Network 面板,看请求状态是
preflight还是cancelled:前者是 OPTIONS 被拦,后者大概率是混合内容(HTTP 资源在 HTTPS 页面加载)或跨域头缺失 - Revel 默认不自动加 CORS 头,必须自己写拦截器。简单方案是在
app/controllers/cors.go里加一个 BEFORE 拦截器,对所有响应写c.Response.Out.Header().Set("Access-Control-Allow-Origin", "*") - 若用 HTTPS 反代,务必在 Nginx 配置里传
X-Forwarded-Proto https,否则 Revel 的c.Request.TLS判断失效,revel.Session().Get()可能拿不到 session - 本地开发用
127.0.0.1访问没问题,但用localhost有时会触发 Safari 的 strict-origin 策略,导致 Cookie 不带,看起来像“登录态丢失”
异步处理出错:goroutine 中 panic 无法被捕获,日志不落盘
Revel 不管理 goroutine 生命周期,你在 controller 里起的 goroutine,panic 后既不会触发 PanicFilter,也不会写进 logs/ 目录。
- 绝对不要在 goroutine 里直接调用
c.Render()或读写c.Params—— controller 实例不是线程安全的,且请求上下文已结束 - 用
recover()包裹 goroutine 主体,把错误发到 channel 或直接打到revel.ERROR日志:revel.ERROR.Printf("async task failed: %v", err) - 如果需要等结果再返回,别用
go func() { ... }(),改用sync.WaitGroup+channel组合,主线程 select 等待,超时走 fallback - 第三方 API 调用建议统一走封装好的
api.DoRequestWithContext(ctx),避免 goroutine 里用全局 timeout,导致连接池耗尽
真正难调试的从来不是报错信息本身,而是错误发生时你根本不知道它发生了——比如异步任务 silently crash,或者 CORS 预检被浏览器直接拦截不发请求。盯住 Network 面板的状态码和 Timing 标签页,比翻 server log 有用十倍。


















