Go Web 编程之 模板(一)

本文详细介绍了Go语言中的模板引擎,包括无逻辑和嵌入逻辑模板引擎的分类,以及Go中的模板基本概念、使用步骤。重点讲解了模板中的动作,如点动作、条件动作、迭代动作、设置动作和包含动作,还提到了模板的创建方式、嵌套模板和块动作。文章以实例代码辅助说明,帮助理解模板在Web编程中的应用。
摘要由CSDN通过智能技术生成

概述

模板引擎是 Web 编程中必不可少的一个组件。模板能分离逻辑和数据,使得逻辑简洁清晰,并且模板可复用。引用第二篇文章《程序结构》一文中的图示,我们可以看到模板引擎在 Web 程序结构中的位置:

模板引擎按照功能可以划分为两种类型:

  • 无逻辑模板引擎:此类模板引擎只进行字符串的替换,无其它逻辑;
  • 嵌入逻辑模板引擎:此类模板引擎可以在模板中嵌入逻辑,实现流程控制/循环等。

这两类模板引擎都比较极端。无逻辑模板引擎需要在处理器中额外添加很多逻辑用于生成替换的文本。而嵌入逻辑模板引擎则在模板中混入了大量逻辑,导致维护性较差。实用的模板引擎一般介于这两者之间。

在Go 语言中,text/templatehtml/template两个库实现模板功能。

模板内容可以是 UTF-8 编码的任何内容。其中用{ { }}包围的部分称为动作{ {}}外的其它文本在输出保持不变。模板需要应用到数据,模板中的动作会根据数据生成响应的内容来替换。

模板解析之后可以多次执行,也可以并行执行,但是注意使用同一个Writer会导致输出交替出现。

模板的内容较多,我将分为两篇文章介绍。本文介绍text/template,包括 Go 模板的基本概念,用法和注意点。下篇文章介绍html/template

初体验

使用模板引擎一般有 3 个步骤:

  • 定义模板(直接使用字符串字面量或文件);
  • 解析模板(使用text/templatehtml/template中的方法解析);
  • 传入数据生成输出。
package main

import (
    "log"
    "os"
    "text/template"
)

type User struct {
    Name string
    Age  int
}

func stringLiteralTemplate() {
    s := "My name is {
  { .Name }}. I am {
  { .Age }} years old.\n"
    t, err := template.New("test").Parse(s)
    if err != nil {
        log.Fatal("Parse string literal template error:", err)
    }

    u := User{Name: "darjun", Age: 28}
    err = t.Execute(os.Stdout, u)
    if err != nil {
        log.Fatal("Execute string literal template error:", err)
    }
}

func fileTemplate() {
    t, err := template.ParseFiles("test")
    if err != nil {
        log.Fatal("Parse file template error:", err)
    }

    u := User{Name: "dj", Age: 18}
    err = t.Execute(os.Stdout, u)
    if err != nil {
        log.Fatal("Execute file template error:", err)
    }
}

func main() {
    stringLiteralTemplate()

    fileTemplate()
}

在可执行程序目录中新建模板文件test,并写入下面的内容:

My name is {
  { .Name }}. I am {
  { .Age }} years old.

首先调用template.New创建一个模板,参数为模板名。

然后调用Template类型的Parse方法,解析模板字符串,生成模板主体。这个方法返回两个值。如果模板语法正确,则返回模板对象本身和一个 nil 值。如果有语法错误,则返回一个 error 类型的值作为第二个返回值,这时不应该使用第一个返回值。

最后,调用模板对象的Execute方法,传入参数。Execute执行模板中的动作,将结果输出到os.Stdout,即标准输出。最终我们看到模板中{ { .Name }}uName字段替换,{ { .Age }}uAge字段替换,标准输出中显示下面一行字符串:

My name is darjun. I am 28 years old.

上面代码中,fileTemplate函数还演示了如何从文件中加载模板。其中template.ParseFiles方法会创建一个模板,并将用户指定的模板文件名用作这个新模板的名字:

t, err := template.ParseFiles("test")

相当于:

t := template.New("test")
t, err := t.ParseFiles("test")

动作

Go 模板中的动作就是一些嵌入在模板里面的命令。动作大体上可以分为以下几种类型:

  • 点动作;
  • 条件动作;
  • 迭代动作;
  • 设置动作;
  • 包含动作。

点动作

在介绍其它的动作之前,我们先看一个很重要的动作,点动作{ { . }})。它其实代表是传递给模板的数据,其他动作或函数基本上都是对这个数据进行处理,以此来达到格式化和内容展示的目的。

对前面的代码示例稍作修改:

func main() {
    s := "The user is {
  { . }}."
    t, err := template.New("test").Parse(s)
    if err != nil {
        log.Fatal("Parse error:", err)
    }

    u := User{Name: "darjun", Age: 28}
    err = t.Execute(os.Stdout, u)
    if err != nil {
        log.Fatal("Execute error:", err)
    }
}

运行程序,标准输出显示:

The user is {darjun 28}.

实际上,{ { . }}会被替换为传给给模板的数据的字符串表示。这个字符串与以数据为参数调用fmt.Sprint函数得到的内容相同。我们可以为User结构编写一个方法:

func (u User) String() string {
    return fmt.Sprintf("(name:%s age:%d)", u.Name, u.Age)
}

这样替换的字符串就是格式化之后的内容了:

The user is (name:darjun age:28).

注意:为了使用的方便和灵活,在模板中不同的上下文内,.的含义可能会改变,下面在介绍不同的动作时会进行说明。

条件动作

在介绍动作的语法时,我采用 Go 标准库中的写法。我觉得这样写更严谨。其中pipeline表示管道,后面会有详细的介绍,现在可以将它理解为一个值。T1/T2等形式表示语句块</

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值