爬虫代码已复制

Golang gin template: "index" is an incomplete or empty template 的解决方法

在使用 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 框架的机制及底层原理。