Go HTML模板跨目录引入报错:找不到nav模板
解决Go html/template找不到子目录模板的问题
这个报错的原因很明确:你当前的模板加载代码只读取了templates根目录下的.gohtml文件,而nav.gohtml放在了templates/includes子目录里,所以模板引擎根本没加载到它,自然找不到名为"nav"的模板。
问题根源
你的init函数里用了:
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
ParseGlob的通配符*.gohtml只会匹配templates目录下直接的文件,不会递归遍历子目录,所以includes/nav.gohtml完全没被加载。而header.gohtml和index.gohtml在同一目录,所以能正常被识别。
解决方案
这里有几种可行的解决方法,按推荐程度排序:
1. 递归加载所有子目录的模板文件(最推荐)
Go 1.16及以上版本支持filepath.Glob的**通配符,可以递归匹配所有子目录里的.gohtml文件。修改你的init函数:
import ( "html/template" "log" "net/http" "path/filepath" // 新增这个包 ) var tpl *template.Template func init() { // 递归获取templates目录下所有层级的.gohtml文件 templateFiles, err := filepath.Glob("templates/**/*.gohtml") if err != nil { log.Fatalf("Failed to find template files: %v", err) } // 用ParseFiles加载所有找到的文件 tpl = template.Must(template.ParseFiles(templateFiles...)) }
这样不管你把模板放在templates下的哪个子目录,都会被加载进来。
2. 显式列出所有模板文件(适合模板数量少的场景)
如果你的模板不多,可以直接在ParseFiles里把所有需要的文件路径都列出来:
func init() { tpl = template.Must(template.ParseFiles( "templates/index.gohtml", "templates/header.gohtml", "templates/includes/nav.gohtml", // 其他模板文件也可以在这里添加 )) }
这种方式虽然直观,但模板多了之后维护起来很麻烦,不推荐长期使用。
3. 检查模板定义是否正确
最后别忘了确认nav.gohtml里的模板定义格式是否正确,必须用{{define "nav"}}和{{end}}包裹内容,比如:
{{define "nav"}} <nav> <a href="/">Home</a> <a href="/apply">Apply</a> </nav> {{end}}
如果没有这个定义,即使文件被加载了,模板引擎也找不到名为"nav"的模板。
验证修改
修改完代码后,重启你的Go服务,访问首页应该就不会再出现no such template "nav"的错误了。
内容的提问来源于stack exchange,提问作者Reza Saadati
相关产品推荐
相关产品推荐

