beego autorouter 仅识别 controllers/ 目录下包名为 controllers、结构体直接嵌入 web.controller、方法名严格为大写 http 动词(如 get、post)的控制器;否则 404 静默失败。

Beego 的接口开发不靠手写路由注册就能跑起来,但前提是控制器命名、嵌入、方法签名都严格符合约定;否则 bee run 启动后访问 404,连日志都不报错。
为什么新建的 Controller 方法不被路由识别?
Beego 默认启用 AutoRouter,但它只扫描 controllers/ 目录下满足三个硬性条件的结构体:
- 结构体必须直接嵌入
web.Controller(不是组合、不是指针、不能跳过) - 方法名必须首字母大写 + HTTP 动词前缀,比如
Get()、Post()、Delete()(get()或DoGet()都无效) - 文件必须放在
controllers/下,且包名必须是controllers
常见错误示例:func (c *MainController) HandleGet() 不会被识别;func (c *MainController) get() 也不会被识别;package api 放在 controllers 目录下照样失效。
如何让 /user/:id 这类路径自动传参到方法?
AutoRouter 支持路径参数绑定,但规则极简且不容妥协:
- URL 路径写成
/user/:id,对应方法签名必须是Get(id string),参数名和类型必须完全一致 -
:id总是作为string传入,要转int得手动调c.Ctx.Input.Param(":id")再用c.GetInt() - 不能写成
/user/:id/profile/:id—— 后一个:id会覆盖前一个,只留最后一个值 - 如果想支持多种动词(如 POST /user/:id),就写
Post(id string),框架自动匹配
示例正确写法:
func (c *UserController) Get(id string) {
uid, err := c.GetInt(":id")
if err != nil {
c.Abort("400")
return
}
c.Data["json"] = map[string]interface{}{"id": uid}
c.ServeJSON()
}
bee run 启动后访问 404,但没报错,怎么排查?
这不是网络或端口问题,而是 Beego 在静默跳过不合规的控制器。排查顺序如下:
- 确认
main.go中是否导入了路由包:_ "myapp/routers"(下划线必须有,否则init()不执行) - 检查
routers/router.go是否存在,且其中init()函数里有没有显式调用beego.Router或beego.Include - 如果没写
routers/,那就完全依赖 AutoRouter —— 此时立刻检查控制器文件路径、包名、结构体嵌入、方法命名这四点 - 运行
bee run -d开启 debug 模式,看控制台是否打印出 “Auto register controller” 类似日志
特别注意:bee run 不会重新编译 routers/ 外的目录,改了 controllers/ 文件后必须重启才能生效。
API 返回 JSON 却提示 template not found?
这是新手最常踩的坑:Beego 默认把所有响应当 HTML 模板处理,除非你明确告诉它这是 JSON。
- 不要用
c.TplName = "xxx",那是给模板用的 - 必须调
c.ServeJSON()或c.Data["json"] = xxx; c.ServeJSON() - 如果用了
c.Ctx.WriteString(),内容不会自动加Content-Type: application/json,前端可能解析失败 -
ServeJSON()会自动设置 header、序列化、加换行,比手写json.Marshal安全得多
返回空 JSON 对象的最小安全写法:
func (c *MainController) Get() {
c.Data["json"] = map[string]interface{}{}
c.ServeJSON()
}
复杂点在于 AutoRouter 和 JSON 响应的耦合逻辑 —— 一旦控制器方法签名或嵌入出错,ServeJSON() 根本不会被执行,你看到的只是 404。所以别急着调接口,先确保结构体和方法能被框架“看见”。











