为什么当我忽略template.New()时,程序可以成功运行?

huangapple go评论75阅读模式
英文:

Why when I ignore the template.New() the program can run successfully?

问题

我正在尝试使用html/template来解析一个结构化格式的JSON。

func handler(w http.ResponseWriter, r *http.Request) {
    var issueList = template.Must(template.New("template01").ParseFiles("template01.tmpl"))
    result, err := SearchIssues(os.Args[1:])
    if err != nil {
        log.Fatal(err)
    }
    if err := issueList.Execute(w, result); err != nil {
        log.Fatal(err)
    }
}

函数SearchIssues用于将流转换为JSON格式,它工作正常。

然后我尝试使用html/template来解析JSON:

var issueList = template.Must(template.New("template01").ParseFiles("template01.tmpl"))

当我访问本地服务时,出现错误:XXX是一个不完整或空的模板

但是当我删除New("template01").后,程序可以正常运行。

像这样:

func handler(w http.ResponseWriter, r *http.Request) {
    var issueList = template.Must(template.ParseFiles("template01.tmpl"))
    result, err := SearchIssues(os.Args[1:])
    if err != nil {
        log.Fatal(err)
    }
    if err := issueList.Execute(w, result); err != nil {
        log.Fatal(err)
    }
}

我不是母语为英语的人,英语不是很好,抱歉。

英文:

I am trying to use html/template to parse a JSON in struct format.

func handler(w http.ResponseWriter, r *http.Request) {
	var issueList = template.Must(template.New("template01").ParseFiles("template01.tmpl"))
	result, err := SearchIssues(os.Args[1:])
	if err != nil {
		log.Fatal(err)
	}
	if err := issueList.Execute(w, result); err != nil {
		log.Fatal(err)
	}
}

The function SearchIssues is used to convert the stream into JSON format, it works well.

Then I try to parse the JSON by html/template using

var issueList = template.Must(template.New("template01").ParseFiles("template01.tmpl"))

When I access local services, there is an error : XXX is an incomplete or empty template.

But when I delete New("template01"). the program runs well.

Like this:

func handler(w http.ResponseWriter, r *http.Request) {
	var issueList = template.Must(template.ParseFiles("template01.tmpl"))
	result, err := SearchIssues(os.Args[1:])
	if err != nil {
		log.Fatal(err)
	}
	if err := issueList.Execute(w, result); err != nil {
		log.Fatal(err)
	}
}

I am not native speaker, English is not very well, sorry.

答案1

得分: 2

你的第一个代码的问题在于当你执行以下代码时:

var issueList = template.Must(template.New("template01").
    ParseFiles("template01.tmpl"))

template.New() 会创建一个名为 "template01" 的新模板。变量 issueList 将引用这个空模板。你调用它的 Template.ParseFiles() 方法,它会解析 "template01.tmpl" 文件并创建一个关联的模板,命名为 "template01.tmpl"。变量 issueList 仍然引用 template01 模板,而不是从文件解析出来的模板。当你调用 Template.Execute() 时,它执行 issueList 指定的(默认)模板,也就是空的 template01。这就是为什么会出现 incomplete or empty template 错误的原因。

在你的第二个版本中:

var issueList = template.Must(template.ParseFiles("template01.tmpl"))

你调用了 template.ParseFiles() 函数,它解析了 "template01.tmpl" 文件,并返回它的模板。所以 issueList 将引用从文件解析出来的模板,而不是空模板。因此,Template.Execute() 将执行这个模板。

注意:如果在第一种情况下你使用 Template.ExecuteTemplate(),你可以指定要执行的模板的名称:

if err := issueList.Execute(w, "template01.tmpl", result); err != nil {
    log.Fatal(err)
}

这将成功,因为你明确告诉它执行从文件解析出来的 "template01.tmpl",而不是默认的空模板。

还要注意的是,你不应该在处理程序中解析模板,这样会很慢。在处理程序之前解析一次,将结果存储在包级别的变量中,然后在处理程序中只执行它即可。详细信息请参见 https://stackoverflow.com/questions/28451675/it-takes-too-much-time-when-using-template-package-to-generate-a-dynamic-web-p/28453523#28453523

关于关联模板的详细信息,请参见 https://stackoverflow.com/questions/41176355/go-template-name/41187671#41187671

另外,请使用 encoding/json 生成 JSON 输出,而不是 text/templatehtml/template。模板引擎对 JSON 格式和编码一无所知,很容易生成无效的 JSON。

英文:

The problem with your first code is that when you do:

var issueList = template.Must(template.New("template01").
    ParseFiles("template01.tmpl"))

template.New() will create a new template having the name "template01". The variable issueList will refer to this empty template. You call its Template.ParseFiles() method, which will parse the "template01.tmpl" file and create an associated template named "template01.tmpl". The variable issueList will still refer to the template01 template, not the one parsed from the file. When you call Template.Excute(), it executes the (default) template issueList designates, which is the empty template01. That's why you get the error incomplete or empty template.

In your second version:

var issueList = template.Must(template.ParseFiles("template01.tmpl"))

You call the template.ParseFiles() function, which parses the "template01.tmpl" file, and returns its template. So issueList will refer to the parsed template from the file, and not an empty template. So Template.Execute() will execute this template.

Note: if in the first case you'd use Template.ExecuteTemplate(), you can name the template you want to execute:

if err := issueList.Execute(w, "template01.tmpl", result); err != nil {
    log.Fatal(err)
}

This will succeed because you tell explicitly to execute the "template01.tmpl" parsed from the file, and not the default, empty template.

Also note that you should not parse the templates in your handler, it's slow. Parse it before that once, store the result in package level variables and just execute it in the handler. For dteails, see https://stackoverflow.com/questions/28451675/it-takes-too-much-time-when-using-template-package-to-generate-a-dynamic-web-p/28453523#28453523

For details about associated templates, see https://stackoverflow.com/questions/41176355/go-template-name/41187671#41187671.

Also please use encoding/json to generate JSON output and not text/template or html/template. The template engine knows nothing about JSON format and encoding, and may easily generate invalid JSON.

huangapple
  • 本文由 发表于 2022年10月5日 18:42:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/73959229.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定