乐趣区

关于golang:Go-语言入门很简单nethttp-包

引言

之前的文章学过把模板和视图拆散,建设一个 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。

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。您应该看到一个看起来像这样的页面。

当咱们不提供名称时,模板将应用空字符串代替值出现。相同,咱们心愿咱们的页面显示一个更通用的字符串,例如“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}}{{.Name}}{{else}}there{{end}}!</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}}
    <span class="price">${{.Price}}</span>
  </div>
{{end}}

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

{{range .Widgets}}
  {{template "widget" .}}
{{end}}

这段代码的最终后果是雷同的,然而当初咱们有了一个小部件模板,咱们能够轻松地在 Web 应用程序的其余页面上重用它,而无需重写代码。

接下来

凭借您新学到的模板技能,您应该能够创立可重用的动静模板。在下一篇文章中,咱们将介绍如何应用内置的模板函数,如 andeqindex,而后咱们将看看如何增加咱们本人的自定义函数。我本来打算包含那些听到的,但这篇文章有很多要介绍的口头,我不想卖空任何一个。

在对于函数的帖子之后,咱们将介绍如何应用模板来创立 Web 应用程序的视图层。这将包含创立共享布局、定义能够被笼罩的默认模板,以及在不同页面中蕴含雷同的模板,而无需将所有代码放入单个文件中。

如果您感到雄心勃勃或好奇,您还能够查看 text/templatehtml/template 的模板文档。持续本人摸索其余一些常识~

退出移动版