Golang template.ParseGlob无法读取根目录文件问题排查
Go模板ParseGlob匹配失败问题分析
问题重现
代码实现
package main import ( "html/template" "os" "path/filepath" ) func main() { // Parse all templates that match the recursive glob pattern templates := template.Must(template.ParseGlob(filepath.Join("templates", "**", "*.gohtml"))) // Execute the base template to render the combined content err := templates.ExecuteTemplate(os.Stdout, "base.gohtml", nil) if err != nil { panic(err) } }
模板目录结构
templates ├── base.gohtml └── nested └── index.gohtml
运行错误
panic: html/template: "base.gohtml" is undefined goroutine 1 [running]: main.main()
将base.gohtml移入nested目录后程序可正常运行。
原因:Glob模式**的匹配规则限制
你使用的匹配模式templates/**/*.gohtml中,**在Go的filepath.Glob规则里仅匹配非空的多级目录,它不会匹配templates根目录下直接的文件。也就是说:
- 该模式能匹配
templates/nested/index.gohtml这类子目录中的文件 - 但无法匹配
templates/base.gohtml这种根目录下的文件
当你把base.gohtml移入nested目录后,它符合**的匹配范围,所以能被正确解析,程序也就正常运行了。
解决方案
要同时匹配templates根目录和所有子目录下的.gohtml文件,可以通过以下两种方式实现:
方式1:合并多个Glob结果,使用ParseFiles解析
package main import ( "html/template" "os" "path/filepath" ) func main() { // 获取根目录下的模板文件 rootTemplates, err := filepath.Glob(filepath.Join("templates", "*.gohtml")) if err != nil { panic(err) } // 获取所有子目录下的模板文件 nestedTemplates, err := filepath.Glob(filepath.Join("templates", "**", "*.gohtml")) if err != nil { panic(err) } // 合并所有文件路径 allTemplates := append(rootTemplates, nestedTemplates...) // 解析所有模板 templates := template.Must(template.ParseFiles(allTemplates...)) err = templates.ExecuteTemplate(os.Stdout, "base.gohtml", nil) if err != nil { panic(err) } }
方式2:遍历多模式匹配
也可以直接定义多个匹配模式,一次性获取所有目标文件:
package main import ( "html/template" "os" "path/filepath" ) func main() { patterns := []string{ filepath.Join("templates", "*.gohtml"), filepath.Join("templates", "**", "*.gohtml"), } var allTemplates []string for _, pattern := range patterns { paths, err := filepath.Glob(pattern) if err != nil { panic(err) } allTemplates = append(allTemplates, paths...) } templates := template.Must(template.ParseFiles(allTemplates...)) err := templates.ExecuteTemplate(os.Stdout, "base.gohtml", nil) if err != nil { panic(err) } }
内容的提问来源于stack exchange,提问作者Adharsh M
相关产品推荐
相关产品推荐

