You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 03:57:23