不能在golang中很好地执行模板

时间:2016-02-06 16:37:50

标签: html http templates go

我正在尝试创建一些模板,但我无法理解下一件事: 为什么这样的建筑不起作用? 我有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) {
    //Parsing 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

1 个答案:

答案 0 :(得分:1)

更新(2016年2月7日)

我将尽力解释为什么你的代码没有被正确执行以及使用嵌套模板的正确解决方案。

在您的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) {
    //Parsing 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 }}

不使用子模板

我对您的代码进行了一些更改,使其正常工作。我只是将struct集合中的'Name'和'City'变量发送到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) {
    //Parsing 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>