在使用 Golang gin 框架开发产品里,在加载 html 模板里,出现了异常信息:template: "index" is an incomplete or empty template,这个异常信息是在路由对应的函数运行的时候才会出现的,而且是在 html 模板目录下有子目录的且子目录与父目录有同名 html 模板文件的情况下才会出现。下面我们来看看这个异常信息出现的原因以及解决方案。
先建立一个 Golang gin 的工程,然后在该工程目录下执行 shell 命令 go get github.com/gin-gonic/gin 引用 gin 框架,工程目录有分别是以下子目录及文件:
- main.go
- go.mod
- go.sum
- templates/layout.html
- templates/index.html
- templates/sub/index.html
各个文件的代码分别如下:
main.go
package main
import (
"log"
"text/template"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.LoadHTMLGlob("templates/**/*")
router.GET("/", index)
router.GET("/sub", sub)
router.Run(":8080")
}
func index(c *gin.Context) {
t, err := template.New("index").ParseFiles("templates/layout.html", "templates/index.html")
if err != nil {
log.Println(err)
}
err = t.Execute(c.Writer, nil)
if err != nil {
log.Println(err)
}
}
func sub(c *gin.Context) {
t, err := template.New("index").ParseFiles("templates/layout.html", "templates/sub/index.html")
if err != nil {
log.Println(err)
}
err = t.Execute(c.Writer, nil)
if err != nil {
log.Println(err)
}
}
templates/layout.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spiderbuf</title>
</head>
<body>
{{- block "content" . -}}
{{- end -}}
</body>
</html>
templates/index.html
{{ block "content" . }}
This is the content of the index page.
{{ end }}
templates/sub/index.html
{{ block "content" . }}
This is the content of the sub page.
{{ end }}
运行以上 Golang 代码,并在浏览器里面访问 http://localhost:8080,这时候会发现浏览器一片空白。返回查看一下 Golang 运行输出的内容,就会看到以下异常信息:
template: index: "index" is an incomplete or empty template
从异常信息里面双引号括起来的 index 就能猜测到,这是跟 index 字符串有关的。难道是因为 index 这个名称重复了?把 template.New() 里的字符串换一个,再运行,发现还是会报同样的错误。
最终的解决方法是直接把 template.New() 这个方法去掉,创建模板对象的代码就变成了:
func index(c *gin.Context) {
t, err := template.ParseFiles("templates/layout.html", "templates/index.html")
if err != nil {
log.Println(err)
}
err = t.Execute(c.Writer, nil)
if err != nil {
log.Println(err)
}
}
sub 函数也是同样的处理,再运行代码时发现问题已经迎刃而解。
其实这个问题的根源是跟 gin 加载模板的机制有关的,主要会跟 router.LoadHTMLGlob("templates/**/") 这行代码有关,如果 html 模板目录没有子目录,则使用 router.LoadHTMLGlob("templates/") 加载模板,且使用 template.New() 来加载模板时是不会出现这个异常信息的。
有兴趣的朋友可以去深入了解一下 gin 框架的机制及底层原理。