59、Go语言基础 - Web 编程 - html-template 模板

作者: 温新

分类: 【Go基础】

阅读: 1452

时间: 2023-12-05 00:53:40

hi,我是温新

Go 语言中的 html/template 包是一个用于生成 HTML、XML 等格式文本的模板系统。它提供了一种简单的方式来生成文本输出,并支持各种数据类型的嵌入。

Go语言的模板引擎

Go语言内置了文本模板引擎text/template和用于HTML文档的html/template

  • 1、模板文件通常定义为.tmpl.tpl为后缀(也可以使用其他的后缀),必须使用UTF8编码;
  • 2、模板文件中使用{{}}包裹和标识需要传入的数据;
  • 3、传给模板的数据通过 . 来访问,若数据比较复杂,通过{{.FieldName}} 来访问;
  • 4、除{{}}包裹的内容外,其他内容均不做修改原样输出。

模板引擎的使用

Go 语言模板引擎的使用可以分为三部分:定义模板文件、解析模板文件和模板渲染.

解析模板文件

1、template.ParseFiles

使用template.ParseFiles解析文件template.ParseFiles函数用于解析一个或多个模板文件,并返回一个*template.Template对象。可以传递一个或多个文件名作为参数,用逗号分隔。该函数会将文件内容解析为模板。

tmpl, err := template.ParseFiles("template1.html", "template2.html")

2、template.ParseGlob

使用template.ParseGlob解析多个文件template.ParseGlob函数允许使用通配符匹配多个文件并解析它们。它会将匹配到的所有文件内容合并成一个模板。

tmpl, err := template.ParseGlob("templates/*.html")

3、template.New

使用template.New创建模板对象:使用template.New创建一个新的模板对象,然后使用其ParseParseFiles方法将模板内容添加到该对象中。

tmpl := template.New("example")
tmpl, err := tmpl.Parse("...template content...")

4、template.Must

使用template.Must包装解析操作:通常,在解析模板时,可以使用template.Must来简化错误处理。template.Must接受一个模板解析函数并返回一个不可变的模板。如果解析失败,它会导致程序崩溃,适用于只有在模板格式正确的情况下才能运行的情况。

tmpl := template.Must(template.ParseFiles("template.html"))

模板渲染

模板渲染是将模板与数据结合以生成最终文本输出的过程。在Go语言中,模板渲染通常使用html/template包进行。

1、Execute

template.Execute方法用于将数据传递给模板并生成渲染后的输出。这是最常用的渲染方法,可以将数据直接传递给模板进行渲染。

tmpl.Execute(w, data)

2、ExecuteTemplate

template.ExecuteTemplate方法允许选择要渲染的具体模板。

tmpl.ExecuteTemplate(w, "main", data)

3、ExecuteTemplate

如果模板包含嵌套模板,可以使用template.ExecuteTemplate方法来渲染嵌套模板。

tmpl.ExecuteTemplate(w, "header", data)
tmpl.ExecuteTemplate(w, "content", data)
tmpl.ExecuteTemplate(w, "footer", data)

4、ExecuteTemplate

ExecuteTemplate方法与嵌套模板:在嵌套模板的情况下,可以使用{{template "TemplateName" .}}语法在模板中调用其他模板,然后使用template.Executetemplate.ExecuteTemplate方法进行渲染。

tmpl.ExecuteTemplate(w, "main", data)

基本案例

定义模板文件

定义一个 1-index.tmpl 模板文件,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Go Web</title>
</head>
<body>
    <h1>Go Web 编程</h1>
    <h2>{{.}}</h2>
</body>
</html>

Go 解析和渲染模板文件

创建一个 1-index.go 文件,内容如下:

package main

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

func main() {
	// 创建 HTTP 服务器,监听在本地的 20000 端口
	http.HandleFunc("/go/web", helloHandler) // 注册路由
	http.ListenAndServe(":20000", nil) // 启动服务器
}

func helloHandler(w http.ResponseWriter, r *http.Request) { // 定义路由处理函数
	tmpl, err := template.ParseFiles("./1-index.tmpl") // 解析模板文件
	if err != nil { // 如果解析失败
		fmt.Println("create template failed, err:", err)
		return
	}
    
    // 使用渲染模板,并将结果写入HTTP响应
    // 第二个参数"自如初"会替换模板中的占位符
	tmpl.Execute(w, "自如初") // 执行模板
}

html/template 模板语法

{{.}}

模板语法都包含在{{}}中间,其中{{.}}中的点表示当前对象。如 {{.Name}}

注释

{{/* 我是注释 */}}

pipeline

在 Go 语言的模板中,可以使用管道(pipeline)来对多个变量进行处理,以生成最终的输出。管道由多个操作符(operator)组成,操作符可以是内置的函数,也可以是自定义的函数。

模板案例:

<!DOCTYPE html>
<html>
  <head>
    <title>{{.Title}}</title>
  </head>
  <body>
    {{/* 将 Title 变量的值转换为大写 */}}
    {{.Title | toupper}}

    <h1>{{.Message}}</h1>

    {{/* 使用自定义函数将 Message 变量的值进行处理 */}}
    {{.Message | myFilter}}
  </body>
</html>

在上面的模板中,| 操作符用于将一个变量传递给一个函数进行处理。toupper 是一个内置的函数,用于将字符串转换为大写,而 myFilter 则是一个自定义的函数,用于对字符串进行处理。

下面是 touppermyFilter 函数的实现:

func toupper(s string) string {
    r := strings.NewReplacer("a", "A", "b", "B", "c", "C", ...)
    return r.Replace(s)
}

func myFilter(s string) string {
    // 对字符串进行处理,返回处理后的字符串
    return s
}

变量

在 Go 语言的模板中,可以使用 {{.}} 语法来获取模板中的当前值。这个值可以是一个变量、一个函数调用、一个控制结构语句等等。

如果想将当前值赋给一个变量,可以使用 $obj := {{.}} 语法。这个语法将会把当前值赋给 $obj 变量。

go 程序案例

package main

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

func main() {
    // 创建一个模板对象
    tmpl := template.Must(template.ParseFiles("template.html"))

    // 渲染模板,并将变量传递给模板
    tmpl.Execute(http.ResponseWriter, map[string]interface{}{
        "Name": "John",
        "Age":  30,
    })
}

下面是一个示例,展示了如何使用 $obj := {{.}} 语法:

<!DOCTYPE html>
<html>
  <head>
    <title>{{.Title}}</title>
  </head>
  <body>
    <h1>{{.Name}}</h1>

    <p>Age: {{.Age}}</p>

    <!-- 将 Age 变量的值赋给 $obj 变量 -->
    <script>
        var obj = {{$obj := .Age}}
        console.log(obj);
    </script>
  </body>
</html>

在上面的模板中,我们首先输出了变量 NameAge 的值。然后,我们使用 {{$obj := .Age}} 语法将变量 Age 的值赋给 $obj 变量。最后,我们使用 console.log 方法输出了 $obj 变量的值。

移除空格

{{- .Name -}}

{{-语法去除模板内容左侧的所有空白符号, 使用-}}去除模板内容右侧的所有空白符号。

注意:-要紧挨{{}},同时与模板值之间需要使用空格分隔。

条件判断

1、{{if}} 条件语句
{{if condition}}
    // 如果 condition 为 true,则执行这里的代码
{{end}}
2、{{if}} 嵌套语句
{{if condition1}}
    {{if condition2}}
        // 如果 condition1 和 condition2 都为 true,则执行这里的代码
    {{else}}
        // 如果 condition1 为 true,但 condition2 为 false,则执行这里的代码
    {{end}}
{{else}}
    // 如果 condition1 为 false,则执行这里的代码
{{end}}
3、{{else}} 语句
{{if condition}}
    // 如果 condition 为 true,则执行这里的代码
{{else}}
    // 如果 condition 为 false,则执行这里的代码
{{end}}
4、{{else if}} 语句
{{if condition1}}
    // 如果 condition1 为 true,则执行这里的代码
{{else if condition2}}
    // 如果 condition1 为 false,但 condition2  为 true,则执行这里的代码
{{else}}
    // 如果 condition1 和 condition2 都为 false,则执行这里的代码
{{end}}

range

在 Go 的 html/template 包中,{{range ...}} ... {{end}} 结构用于在模板中迭代切片、数组、映射等数据结构的元素,以便渲染模板内容。

以下是有关 {{range ...}} 结构的详细说明:

  1. {{range .Slice}} ... {{end}}:这是基本的 range 结构,其中 .Slice 表示要迭代的切片或数组。在 {{range ...}} 结构内部,你可以使用点号 (.) 来引用当前迭代的元素。
  2. {{range .Slice}} ... {{else}} ... {{end}}:这是 {{range ...}} 结构的扩展版本,它允许你指定一个 {{else}} 部分。如果 .Slice 为空或不存在,{{else}} 部分将被执行。
  3. {{range $index, $element := .Slice}} ... {{end}}:这种形式的 range 结构允许你在循环中访问元素的索引和值,分别用 $index$element 表示。这对于需要了解元素索引的情况非常有用。
  4. {{range .Map}} ... {{end}}:除了切片和数组,range 也可以用于映射 (map)。在这种情况下,{{.Map}} 表示要迭代的映射,循环中的 .Key.Value 分别表示键和值。
  5. {{range $key, $value := .Map}} ... {{end}}:与上面的类似,这种形式的 range 结构允许你访问映射中的键和值,分别用 $key$value 表示

下面是一个简单的示例,演示如何在模板中使用 {{range ...}} 结构遍历切片:

{{range .Users}}
  <p>Name: {{.Name}}, Age: {{.Age}}</p>
{{else}}
  <p>No users available.</p>
{{end}}

with

{{with ...}} ... {{end}} 结构用于在模板中设置一个临时的上下文,使你能够在一段模板中访问该上下文中的字段或方法。

以下是有关 {{with ...}} 结构的详细说明:

  • {{with ...}} ... {{end}}with 结构允许你在其中设置一个新的上下文。这个新的上下文通常是一个字段或方法调用,如 {{with .Field}}{{with .Method}}。在 with 结构内部,你可以使用点号 (.) 来引用该新上下文,而不需要在每个字段或方法前使用点号。

with 结构在以下情况下非常有用:

  1. 链式访问:当你需要在模板中多次访问同一个字段或方法时,使用 with 可以减少冗余的点号 (.)。
  2. 增强可读性:在模板中使用 with 可以增强可读性,使模板更具清晰性。

以下是一个示例,演示如何在模板中使用 {{with ...}} 结构:

{{with .User}}
  <h1>Welcome, {{.Name}}!</h1>
  <p>Email: {{.Email}}</p>
{{else}}
  <p>Guest user</p>
{{end}}

比较函数

eq      如果arg1 == arg2则返回真
ne      如果arg1 != arg2则返回真
lt      如果arg1 < arg2则返回真
le      如果arg1 <= arg2则返回真
gt      如果arg1 > arg2则返回真
ge      如果arg1 >= arg2则返回真
请登录后再评论