Gin v1.8.1 LoadHTMLGlob使用**通配符加载模板报无匹配文件错误
问题原因
这是Gin v1.8.1 中LoadHTMLGlob的**递归匹配规则和普遍认知存在偏差导致的:**在Gin的glob实现中,仅代表任意层级的子目录段,因此dir/**/*的匹配范围是dir下所有子目录(不限深度)内的文件,完全不包含dir根目录下直接存放的文件。
如果你的templates目录下没有建任何子文件夹,所有模板文件都直接放在templates根目录,这个模式会匹配到0个有效文件,最终触发html/template.Must的panic,和你贴出的报错完全一致。
你把模式改成../../templates/*后能正常运行,是因为这个模式本身就是匹配templates根目录下的直属文件,刚好适配你当前的模板存放结构,但这个写法不会加载任何子目录内的模板,后续如果加子目录模板会出现加载不到的问题。
解决方案
根据你后续的模板规划选对应方案即可:
- 调整目录结构适配内置规则
如果你后续模板会按模块分目录存放,可以把所有模板移动到templates下的子目录中(比如新建pages存页面、partials存公共片段),确保templates根目录下不直接放模板文件,原r.LoadHTMLGlob("../../templates/**/*")的写法就可以正常递归加载所有子目录内的模板,不会报错。 - 自定义递归逻辑实现全量加载
如果你需要同时加载templates根目录和所有子目录下的模板,不要依赖内置的**匹配规则,自行递归遍历模板目录收集所有符合后缀要求的文件,再调用LoadHTMLFiles加载,参考实现:
import ( "os" "path/filepath" "strings" "github.com/gin-gonic/gin" ) func collectTemplates(root string, suffix string) ([]string, error) { var files []string err := filepath.Walk(root, func(path string, info os.FileInfo, walkErr error) error { if walkErr != nil { return walkErr } if !info.IsDir() && strings.HasSuffix(info.Name(), suffix) { files = append(files, path) } return nil }) return files, err } func main() { r := gin.Default() cwd, err := os.Getwd() if err != nil { panic(err) } // 第二个参数改成你实际用的模板后缀,比如 .tmpl、.gohtml tplFiles, err := collectTemplates(filepath.Join(cwd, "../../templates"), ".html") if err != nil { panic(err) } r.LoadHTMLFiles(tplFiles...) // 后续路由、服务启动逻辑 r.Run() }
这个方案不受Gin内置glob匹配逻辑的限制,不管模板放在根目录还是任意深度的子目录都能正常加载,也不会出现零匹配触发panic的问题,稳定性更高。
内容的提问来源于stack exchange,提问作者Paul Waldo
相关产品推荐
相关产品推荐

