Go Web 编程入门: 动态模板

Posted 宇宙之一粟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go Web 编程入门: 动态模板相关的知识,希望对你有一定的参考价值。

之前的文章学过把模板和视图分离,建立一个 Web 服务器来展现 html 模板。我们将学习如何使用 Go 的模板包创建动态 HTML 和文本文件。

建立 Web 服务器

到目前为止,我们一直在向终端输出模板,但是当我们开始深入研究更多 HTML 时,这开始变得不那么有意义了。相反,我们希望可视化在 Web 浏览器中生成的 HTML。为此,我们首先需要设置一个 Web 服务器来呈现我们的 HTML 模板。

package main

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

var testTemplate *template.Template

type ViewData struct
Name string


func main()

var err error
testTemplate, err = template.ParseFiles("hello.gohtml")
if err != nil
panic(err)


http.HandleFunc("/", handler)
http.ListenAndServe(":8000", nil)


func handler(w http.ResponseWriter, r *http.Request)

w.Header().Set("Content-Type", "text/html")

vd := ViewData"Kyrie Jobs"

err := testTemplate.Execute(w, vd)
if err != nil
http.Error(w, err.Error(), http.StatusInternalServerError)

创建一个名为 ​​hello.gohtml​​ 的文件并将以下内容添加到其中:

<h1>Hello, .Name!</h1>

现在通过在终端中输入 ​​go run main.go​​ 来启动服务器。该程序应保持运行并在端口 8000 上侦听 Web 请求,因此您可以在 ​​localhost:8000​​ 查看呈现的 HTML。

Go

if...else 块

我们当前的模板很无聊,因为它只打印出一个人的名字。但是如果没有提供名字会发生什么?

让我们试试看。打开你的 ​​main.go​​ 文件并删除你的 ​​handler()​​ 函数中创建 ​​ViewData​​ 实例的代码,而是向 ​​testTemplate.Execute​​ 方法提供 nil 。完成后,您的 ​​handler()​​ 函数应如下所示:

func handler(w http.ResponseWriter, r *http.Request) 
w.Header().Set("Content-Type", "text/html")

err := testTemplate.Execute(w, nil)
if err != nil
http.Error(w, err.Error(), http.StatusInternalServerError)

现在重新启动您的服务器(或让新服务器重新启动)并在浏览器中访问该页面 - ​​localhost:8000​​。您应该看到一个看起来像这样的页面。

Go

当我们不提供名称时,模板将使用空字符串代替值呈现。相反,我们希望我们的页面显示一个更通用的字符串,例如“Hello, there!”。让我们继续更新模板以使用我们的第一个操作,即 ​​if/else​​ 块。像这样更新 ​​hello.gohtml​​:

<h1>Hello, if .Name .Name else there end!</h1>

如果您在浏览器中查看该页面,您应该会看到这更新了您的模板以显示“Hello, there !”就像我们想要的那样,但不幸的是,这在“there”这个词和感叹号之间增加了一个额外的空格。大多数时候这并不重要,但是在处理文本时,这有时会很烦人。在下一节中,我们将看看两个选项来稍微清理一下。

为了摆脱额外的空白,我们有几个选择:

  1. 从我们的模板中删除它们。
  2. 使用减号 (-) 告诉模板包修剪多余的空白。

第一个选项非常简单。我们只需将 ​​hello.gohtml​​ 文件更新为并删除多余的空格。

<h1>Hello, if .Name.Nameelsethereend!</h1>

在这个例子中,这很好用,因为它是一段非常短的文本,但是想象一下我们正在生成 python 代码,其中间距很重要 - 这很快就会变得非常烦人。幸运的是,模板包还提供了一种使用减号来修剪不需要的空白的方法。

<h1>
Hello,
if .Name
.Name
- else
there
- end!
</h1>

在此代码片段中,我们通过将减号字符放在 else 关键字的前面来告诉模板包,我们不希望 Name 变量及其后面的任何内容之间的所有空格,并且我们也对 end 执行相同操作倒数第二行的关键字。重新加载您的页面,您应该会看到该空格不再存在。

对于本教程的其余部分,我将选择使用此处的第一个示例作为我的 ​​hello.html​​ 文件。

范围块

现在让我们假设您想在您的网站上显示所有小部件以及它们的价格。这是动态 Web 应用程序的任务类型,因为没有人愿意为您销售的每件商品手动创建 HTML 并维护它。相反,我们希望对每个项目使用相同的 HTML。在 Go 中,您可以使用模板内的范围块来实现此目的。

range .Widgets
<div class="widget">
<h3 class="name">.Name</h3>
<span class="price">$.Price</span>
</div>
end

如果你重启你的服务器(或者让新的)并在 ​​localhost:8000​​ 重新加载页面,你现在应该会看到一个 HTML 页面,其中显示了三个小部件,每个小部件都有一个标题和一个价格。如果我们在数组中添加更多小部件,我们会在这里看到更多,如果我们将其保留为空数组,我们将不会在此处看到任何小部件。

与 ​​range​​ 操作混淆的最常见来源是我们正在访问小部件的各个属性,而无需在 ​​.Widgets​​ 值内使用索引或任何其他访问器。这是因为范围操作会将集合中每个对象的值设置为范围块内的点 (​​.​​)。例如,如果您要在范围块内渲染 ​​.​​,您将看到与在 Widget 对象上使用 ​​fmt.Println()​​ 相同的输出。

嵌套模板

随着您的模板开始增长,您会很快发现您需要在不同的地方重用组件。这就是嵌套模板来拯救这一天的地方。使用 Go 的模板包,您可以声明多个唯一命名的模板,然后当您需要在代码中使用另一个模板时,您只需使用 template 关键字引用它。例如,假设您想为您的网站声明一个页脚,您可以将其包含在多个页面和多个布局中。将以下页脚模板添加到 ​​hello.html​​ 文件中。你把它放在哪里并不重要,但我更喜欢把它放在文件的顶部。

define "footer"
<footer>
<p>
Copyright 2016 Calhoun.io
</p>
<p>
Contact information: <a href="mailto:jon@calhoun.io">jon@calhoun.io</a>.
</p>
</footer>
end

然后在小部件的范围块之后插入以下行。

template "footer"

您的 ​​hello.gohtml​​ 文件应如下所示:

define "footer"
<footer>
<p>
Copyright 2016 Calhoun.io
</p>
<p>
Contact information: <a href="mailto:jon@calhoun.io">jon@calhoun.io</a>.
</p>
</footer>
end

range .Widgets
<div class="widget">
<h3 class="name">.Name</h3>
<span class="price">$.Price</span>
</div>
end

template "footer"

现在,如果您查看 ​​localhost:8000​​,您将看到该页面正在使用您定义的页脚模板。当您定义一个模板时,您可以在任何其他模板中使用它,甚至可以多次使用它。尝试包含页脚模板两次以了解我的意思。

模板变量

我们的上一个示例很棒,但是当您需要在嵌套模板中包含一些数据时会发生什么?幸运的是,模板操作允许您传入第二个参数,该参数将分配给模板内的点 (​​.​​) 参数。例如,假设我们想为小部件的名称标题部分编写模板,我们可以使用以下代码来实现。

define "widget-header"
<h3 class="name">.</h3>
end

range .Widgets
<div class="widget">
template "widget-header" .Name
<span class="price">$.Price</span>
</div>
end

在这种情况下,​​.Name​​ 属性被分配给 widget-header 模板内的点 (​​.​​) 属性。

带有模板变量的嵌套模板甚至允许您深入多层,这意味着可以从模板内部调用模板。

define "widget"
<div class="widget">
template "widget-header" .Name
Go Web 编程之 模板

Go Web编程实战(10)----模板引擎库text/template包的使用

Go Web编程实战(10)----模板引擎库text/template包的使用

Go Web编程实战(10)----模板引擎库text/template包的使用

Go Web 编程入门:验证器

Go Web编程.基础入门