在golang中无法正确执行模板。

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

Cant execute template well in golang

问题

我正在尝试创建一些模板,但是我无法理解下面的问题:
为什么这个结构不起作用?
我有一个test.go文件:

package main
 
import (
	"net/http"
	"html/template"
	"fmt"
)

func main() {
	http.HandleFunc("/test.html", TestHandler)
	http.ListenAndServe(":8080", nil)
}

func TestHandler(w http.ResponseWriter, r *http.Request) {
	//解析HTML
	t, err := template.ParseFiles("test.html")
	if err != nil {
		fmt.Println(err)
	}
	Name := "MyName"
	City := "MyCity"
	t.ExecuteTemplate(w, "T1", Name)
	t.ExecuteTemplate(w, "T2", City)
}

我还有一个test.html文件:

<html>
<head>
	<title>Tamplates</title>
</head>
<body>
	<h1>Testing some templates</h1>
	<p> Empty template: {{ `Some text` }} </p>
	<p> Name is {{ template "T1" . }} </p>
	<p> City is {{ template "T2" . }} </p>
</body>
</html>

这是一个简单的示例,但不知何故它不起作用。
我尝试在h1标题之前添加字符串{{ define "T1" }} {{ . }} {{ end }}{{ define "T2" }} {{ . }} {{ end }},但结果只是网页上显示了字符串"MyName MyCity"。

英文:

I'm trying to create some templates and I just can't understand the next thing:
Why doesn't such construction work?
I've got test.go file:

package main

import (
	&quot;net/http&quot;
	&quot;html/template&quot;
	&quot;fmt&quot;
)

func main() {
	http.HandleFunc(&quot;/test.html&quot;, TestHandler)
	http.ListenAndServe(&quot;:8080&quot;, nil)
}

func TestHandler(w http.ResponseWriter, r *http.Request) {
	//Parsing HTML
	t, err := template.ParseFiles(&quot;test.html&quot;)
	if err != nil {
		fmt.Println(err)
	}
	Name := &quot;MyName&quot;
	City := &quot;MyCity&quot;
	t.ExecuteTemplate(w, &quot;T1&quot;, Name)
	t.ExecuteTemplate(w, &quot;T2&quot;, City)
}

And I also have test.html:

&lt;html&gt;

&lt;head&gt;
    &lt;title&gt;Tamplates&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;Testing some templates&lt;/h1&gt;
    &lt;p&gt; Empty template: {{ `&quot;Some text&quot;` }} &lt;/p&gt;
    &lt;p&gt; Name is {{ template &quot;T1&quot; . }} &lt;/p&gt;
    &lt;p&gt; City is {{ template &quot;T2&quot; . }} &lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;

It's easy example, but somewhy it doesnt work.
I tried adding strings {{ define &quot;T1&quot; }} {{ . }} {{ end }} and {{ define &quot;T2&quot; }} {{ . }} {{ end }}before h1 header, but it has resulted web page containing just string MyName MyCity

答案1

得分: 4

更新(2016年7月2日)

我将尽力解释为什么你的代码没有正确执行,并提供一个使用嵌套模板的正确解决方案。

在你的test.html文件中,你导入了两个模板:T1T2

<p> Name is {{ template "T1" . }} </p>
<p> City is {{ template "T2" . }} </p>

这些模板应该在某个地方定义和编写,以便使用(可以将它们写在单独的文件中)。这是我发现的第一个问题,这是你如何定义它们的:

{{ define "T1" }} {{ . }} {{ end }}
{{ define "T2" }} {{ . }} {{ end }}

注意,{{.}}是当前对象的简写形式,因此它将呈现调用ExecuteTemplate函数时传递的任何数据。因此,为了解决这个问题,你应该指定要在每个模板中呈现的对象:

{{ define "T1" }} {{ .Name }} {{ end }}
{{ define "T2" }} {{ .City }} {{ end }}

现在,这是我发现的第二个问题。在你的TestHandler函数中,你只是渲染了子模板,首先是T1模板,然后是T2模板:

t.ExecuteTemplate(w, "T1", Name)
t.ExecuteTemplate(w, "T2", City)

所以在任何时候,你都没有调用父模板。

下面是使用嵌套模板的示例。希望它能解决你对如何使用模板的疑问。

test.go文件

package main

import (
    "fmt"
    "html/template"
    "net/http"
)

func main() {
    http.HandleFunc("/test.html", TestHandler)
    http.ListenAndServe(":8080", nil)
}

func TestHandler(w http.ResponseWriter, r *http.Request) {
    //解析HTML
    t, err := template.ParseFiles("test2.html", "t1.tmpl", "t2.tmpl")
    if err != nil {
        fmt.Println(err)
    }
    items := struct {
        Name string
        City string
    }{
        Name: "MyName",
        City: "MyCity",
    }
    t.Execute(w, items)
}

test.html文件

<html>
    <head>
        <title>Templates</title>
    </head>
    <body>
        <h1>Testing some templates</h1>
        <p> Empty template: {{ `"Some text"` }} </p>
        <p> Name is {{ template "T1" . }} </p>
        <p> City is {{ template "T2" . }} </p>
    </body>
</html>

t1.tmpl文件

{{ define "T1" }} {{ .Name }} {{ end }}

t2.tmpl文件

{{ define "T2" }} {{ .City }} {{ end }}

不使用子模板

我对你的代码进行了一些更改,使其能够工作。我只是将NameCity变量作为结构集合发送到Execute方法中。请查看下面的代码:

package main

import (
	"fmt"
	"html/template"
	"net/http"
)

func main() {
	http.HandleFunc("/test.html", TestHandler)
	http.ListenAndServe(":8080", nil)
}

func TestHandler(w http.ResponseWriter, r *http.Request) {
	//解析HTML
	t, err := template.ParseFiles("test.html")
	if err != nil {
		fmt.Println(err)
	}

	items := struct {
		Name string
		City string
	}{
		Name: "MyName",
		City: "MyCity",
	}

	t.Execute(w, items)
}

并使用{{.Name}}{{.City}}来访问这些导出字段。

<html> 
    <head>
        <title>Tamplates</title>
    </head>
    <body>
        <h1>Testing some templates</h1>
        <p> Name is {{.Name}} </p>
        <p> City is {{.City}} </p>
    </body>
</html>
英文:

Update (07/02/2016)

I'm gonna to try to explain as best I can why your code was not been executed properly and a proper solution using nested templates.

In your test.html file you were importing two templates: T1 and T2,

&lt;p&gt; Name is {{ template &quot;T1&quot; . }} &lt;/p&gt;
&lt;p&gt; City is {{ template &quot;T2&quot; . }} &lt;/p&gt;

those templates should be defined and write in somewhere to be used (a good place to be written could be in separate files). Here is the first issue that I found, this is how you defined them:

{{ define &quot;T1&quot; }} {{ . }} {{ end }}
{{ define &quot;T2&quot; }} {{ . }} {{ end }}

Note that the {{.}} is a shorthand for the current object, so it will render whatever the data you pass when calling the ExecuteTemplate function. So, to solve this issue, you should specify which object you want to render in each template:

{{ define &quot;T1&quot; }} {{ .Name }} {{ end }}
{{ define &quot;T2&quot; }} {{ .City }} {{ end }}

Now, here is the second issue that I found. In your TestHandler function, you are just rendering the sub-templates, firstly the T1 template, and secondly the T2 template:

t.ExecuteTemplate(w, &quot;T1&quot;, Name)
t.ExecuteTemplate(w, &quot;T2&quot;, City)

so at no time, you are calling to the parent template.

Below you can find how it will look like using nested templates. I hope it will solve your doubt about how to use the templates.

test.go file

package main

import (
    &quot;fmt&quot;
    &quot;html/template&quot;
    &quot;net/http&quot;
)

func main() {
    http.HandleFunc(&quot;/test.html&quot;, TestHandler)
    http.ListenAndServe(&quot;:8080&quot;, nil)
}

func TestHandler(w http.ResponseWriter, r *http.Request) {
    //Parsing HTML
    t, err := template.ParseFiles(&quot;test2.html&quot;, &quot;t1.tmpl&quot;, &quot;t2.tmpl&quot;)
    if err != nil {
        fmt.Println(err)
    }
    items := struct {
        Name string
        City string
    }{
        Name: &quot;MyName&quot;,
        City: &quot;MyCity&quot;,
    }
    t.Execute(w, items)
}

test.html file

&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Templates&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;Testing some templates&lt;/h1&gt;
        &lt;p&gt; Empty template: {{ `&quot;Some text&quot;` }} &lt;/p&gt;
        &lt;p&gt; Name is {{ template &quot;T1&quot; . }} &lt;/p&gt;
        &lt;p&gt; City is {{ template &quot;T2&quot; . }} &lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;

t1.tmpl file

{{ define &quot;T1&quot; }} {{ .Name }} {{ end }}

t2.tmpl file

{{ define &quot;T2&quot; }} {{ .City }} {{ end }}

Without using sub-templates:

I did some changes in your code that made it work. I just send the 'Name' and 'City' variable in a struct collection to the Execute method. Check below:

package main

import (
	&quot;fmt&quot;
	&quot;html/template&quot;
	&quot;net/http&quot;
)

func main() {
	http.HandleFunc(&quot;/test.html&quot;, TestHandler)
	http.ListenAndServe(&quot;:8080&quot;, nil)
}

func TestHandler(w http.ResponseWriter, r *http.Request) {
	//Parsing HTML
	t, err := template.ParseFiles(&quot;test.html&quot;)
	if err != nil {
		fmt.Println(err)
	}

	items := struct {
		Name string
		City string
	}{
		Name: &quot;MyName&quot;,
		City: &quot;MyCity&quot;,
	}

	t.Execute(w, items)
}

And using {{.Name}} and {{.City}} to access to those exported fields.

&lt;html&gt; 
    &lt;head&gt;
        &lt;title&gt;Tamplates&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;Testing some templates&lt;/h1&gt;
        &lt;p&gt; Name is {{.Name}} &lt;/p&gt;
        &lt;p&gt; City is {{.City}} &lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;

huangapple
  • 本文由 发表于 2016年2月7日 00:37:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/35243493.html
匿名

发表评论

匿名网友

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

确定