r.HTML()调用成功需路径、扩展名、目录结构三者严格对齐,模板须置于templates/下并匹配路由约定,仅识别.html和.plush.html,自定义函数须在app.go中显式注册,且HTML与JSON渲染共存时需谨慎处理Content-Type。

r.HTML() 调用成功的关键不是“写了模板”,而是路径、扩展名、目录结构三者严格对齐——错一个就报 template not found。
模板文件必须放在 templates/ 下且命名符合路由约定
Buffalo 不会自动扫描任意路径,只认 templates/ 目录及其子目录。比如你注册了 app.GET("/admin/dashboard", DashboardHandler),那它默认找的是:templates/admin/dashboard.html 或 templates/admin/dashboard.plush.html。
常见错误:
- 把模板放错位置,例如
views/dashboard.html—— Buffalo 完全忽略 - 路径大小写不一致,如路由是
/users,但模板写成Templates/Users/index.html(Linux 环境下直接 404) - 用了
buffalo new --api创建项目,templates/目录被删光,此时调r.HTML("home")必 panic
r.HTML() 查找顺序和扩展名限制
调用 r.HTML("users/index") 时,Buffalo 按固定顺序尝试加载:
templates/users/index.htmltemplates/users/index.plush.htmltemplates/users/index/index.html
注意:
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 不识别
.gohtml、.html.plush、.plush等变体,只认.html和.plush.html - 如果
templates/users/下只有show.gohtml,它不会匹配,也不会提示“找到类似文件”,只会报template not found - 子目录名即命名空间,
templates/api/v1/users/list.html对应的路径是"api/v1/users/list",不能简写为"list"
自定义函数必须在 app.go 中显式注册
Plush 模板引擎不自动导入 Go 函数,{{ required .Name }} 这类调用若未注册,会静默渲染为空,或报 function not defined。
必须在 app.go 的 App() 函数内、buffalo.New() 之后添加:
plush.RegisterFunc("required", func(s string) bool {
return s != ""
})
注意事项:
- 函数签名只能是基础类型(
string,int,bool,struct),不能含interface{}、指针、channel - 参数个数必须固定,Plush 不支持变参或泛型推导
- 注册时机很关键:放在
app = buffalo.New()前无效;放在中间件注册之后也来得及,但别拖到 handler 里
HTML 渲染与 JSON 渲染共存时 Content-Type 易被误判
r.Auto() 会根据 Accept 请求头自动选 HTML 或 JSON,但在前后端分离场景下极易出错:
- 前端发
Accept: */*,Buffalo 默认 fallback 到 HTML,返回 200 + HTML 内容,前端 JS 拿到乱码 - Postman 默认发
Accept: */*,你以为在测 API,其实走的是模板流程 - 浏览器地址栏直输 URL,
Accept: text/html,application/xhtml+xml,必然走 HTML,哪怕你后端逻辑只想返回 JSON
解决方式:
- 纯 API 服务:禁用
r.Auto(),所有 endpoint 统一用c.JSON(200, data) - 需要多格式支持:显式判断
c.Request().Header.Get("Accept"),再分支调用r.HTML()或r.JSON() - 避免在模板里做任何业务逻辑——数据库查询、HTTP 调用都应在 handler 完成,再把结果塞进
c.Data
r.HTML("xxx") 调用时那一瞬间的路径解析规则、扩展名匹配逻辑、以及函数注册是否生效——这三处全靠手敲,没有自动纠错,错一点就黑屏或空响应。

















