无闻Web3.进阶模板用法

在模板中定义变量

变量不仅是Go语言中程序代码的重要组成部分,同样也是模板引擎中的主要元素。因为只有通过定义和操作变量,才能使得模板引擎在逻辑和用法上更加灵活和便利。

text/template包提供的文本模板引擎支持使用字母数字(Alphanumeric)作为变量的名称,并使用一个美元符号($)作为前缀,例如:$name$age$round2。在模板中定义语法和程序代码中类似,即使用:=链接变量名和赋值语句。

package main

import (
    "fmt"
    "log"
    "net/http"
    "text/template"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 创建模板对象并解析模板内容
        tmpl, err := template.New("test").Parse(`
{{$name := "Alice"}}
{{$age := 18}}
{{$round2 := true}}
Name: {{$name}}
Age: {{$age}}
Round2: {{$round2}}
`)
        if err != nil {
            fmt.Fprintf(w, "Parse: %v", err)
            return
        }

        // 调用模板对象的渲染方法
        err = tmpl.Execute(w, nil)
        if err != nil {
            fmt.Fprintf(w, "Execute: %v", err)
            return
        }
    })

    log.Println("Starting HTTP server...")
    log.Fatal(http.ListenAndServe("localhost:4000", nil))
}

不难发现,这个示例的核心就是包含变量使用的模板内容:

{{$name := "Alice"}}
{{$age := 18}}
{{$round2 := true}}
Name: {{$name}}
Age: {{$age}}
Round2: {{$round2}}

在这里,我们需要主要的是以下三点:

  1. 变量的定义(或首次获得赋值)必须使用:=的语法
  2. 获取变量值时,直接在相应位置使用美元符号加上变量名称即可
  3. 所有有关变量的操作都属于模板语法的一部分,因此需要使用双层大括号将其包裹起来

那么,在变量被定义之后,如何修改变量的值呢?很简单,只需要和程序代码中那样,直接使用等号(=)即可:

{{$name = "Bob"}}

在模板中使用条件判断(if语句)

基本if模板

{{if .yIsZero}}
	除数不能为0
{{else}}
	{{.result}}
{{end}}

模板中的等式与不等式

如果所有的条件判断都只能在程序代码中完成,然后直接输出给模板计算好的条件,未免有点太不方便。因此,Go语言的文本模板引擎同样可以在模板中完成等式与不等式的判断,为更加复杂的条件判断提供了必要的支持。

用于等式与不等式判断的函数主要有以下六种(均接受两个,分别名为arg1arg2的参数):

  • eq:当等式arg == arg2成立时,返回true,否则返回false
  • ne:当不等式arg1 != arg2成立时,返回true,否则返回false
  • lt:当不等式arg1 < arg2成立时,返回true,否则返回false
  • le:当不等式arg1 <= arg2成立时,返回true,否则返回false
  • gt:当不等式arg1 > arg2成立时,返回true,否则返回false
  • ge:当不等式arg1 >= arg2成立时,返回true,否则返回false

如果你对这些函数的名字感到奇怪,其实不难发现这些名字本质上就是相关英文的缩写。如"eq"是"equal"的缩写,“ne"表示"not equal”,“lt"表示"less than”,"le"表示"less than or equal"等等。

接下来,我们就结合目前所学的知识,将更多的判断逻辑放置到模板当中完成。

{{$name1 := "alice"}}
{{$name2 := "bob"}}
{{$age1 := 18}}
{{$age2 := 23}}

{{if eq $age1 $age2}}
	年龄相同
{{else}}
	年龄不同
{{end}}

{{if ne $name1 $name2}}
	名字不同
{{end}}

{{if gt $age1 $age2}}
	alice 年龄比较大
{{else}}
	bob 年龄比较大
{{end}}

你可能会对这个例子中if条件语句的用法感到怪异,这是因为eqnegt等本质上属于函数,而函数的调用都是以函数名称(参数1,参数2,...)的形式,只是在大部分情况下,Go语言标准库提供的这套模板引擎可以在语法上省略括号的使用

在模板中使用迭代操作(range语句)

除了可以在模板中进行条件判断以外,Go语言标准库提供的模板引擎还支持通过range语句进行迭代操作,以方便直接在模板中对集合类型的数据进行处理和渲染

Go语言中一般来说有三种类型可以进行迭代操作,数组(Array)、切片(Slice)和map类型。

package main

import (
	"fmt"
	"log"
	"net/http"
	"text/template"
)

func main() {
	http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request) {
		// 创建模板对象并解析模板内容
		tmpl, err := template.New("test").Parse(`
		{{range $name := .Names}}
			{{$name}}
		{{end}}`)
	}
	if err != nil {
		fmt.Fprintf(w,"Parse: %v",err)
		return
	}
	// 调用模板对象的渲染方法
	err = tmpl.Execute(w,map[string]interface{}{"Names":[]string{"Alice","Bob","Carol","David"}})
	if err != nil {
		fmt.Fprintf(w,"Execute:%v",err)
		return
	}
})

	log.Println("Starting HTTP server...")
    log.Fatal(http.ListenAndServe("localhost:4000", nil))

上例中的代码作用非常简单,即先通过map[string]interface{}类型的根对象传递一个名为"Names"的切片,该切片包含了四个人民。然后通过模板的range语句对这个切片进行迭代,依次输出每个人名。

值得注意的是,这里我们使用的语法结构为range $name := .Names,其中,.Names是被迭代的集合,而变量$name则是当次迭代中获取到的单个对象。在本例中,变量$name实际上为string类型。

range语句除了可以获取到当次迭代的对象以外,还能够和Go语言源代码中一样,获取到一个当前迭代所对应的索引值。

func main() {
	http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request) {
		// 创建模板对象并解析模板内容
		tmpl, err := template.New("test").Parse(`
		{{range $i, $name := .Names}}
			{{$i}} : {{$name}}
		{{end}}`)
	})
}

在模板中使用语境操作(with语句)

在学习如何使用语境操作(with语句)之前,我们先来看一看下面的示例:

package main

import (
	"fmt"
	"log"
	"net/http"
	"text/template"
)

type Inventory struct {
	SKU			string
	Name		string
	UnitPrice	float64
	Quantity	int64
}

func main() {
	http.HandleFunc("/",func(w http.ResponseWriter,r *http.Request) {
		// 创建模板对象并解析模板内容
		tmpl, err := template.New("test").Parse(`Inventory
		SKU: {{.Inventory.SKU}}
		Name: {{.Inventory.Name}}
		UnitPrice: {{.Inventory.UnitPrice}}
		Quantity: {{.Inventory.Quantity}}`)
		if err != nil {
			fmt.Fprintf(w,"Parse:%v",err)
			return
		}
		// 调用模板对象的渲染方法
		err = tmpl.Execute(w,map[string]interface{}{
		"Inventory": Inventory{
			SKU:	"11000",
			Name:	"phone",
			UnitPrice: 699.99,
			Quantity: 666}})
		if err != nil {
			fmt.Fprintf(w,"Execute:%v",err)
			return
		} 
	})
	
	log.Println("Starting HTTP server...")
	log.Fatal(http.ListenAndServe("localhost:4000",nil))
}

细看一下模板内容,为了能够渲染"Inventory"的每一个值,我们都需要先通过点操作获取根对象中键名为"Inventory"的对象,然后再通过第二次操作才能获取到某个字段的值。

在模板内容较少的情况下,这样做没什么问题,但是但"Inventory"对象需要被使用非常多次数,就会显得非常冗余。为了解决这个问题,就可以使用语境操作(with语句)。

tmpl,err := template.New("test").Parse(`Inventory
	{{with .Inventory}}
		SKU: {{.SKU}}
    	Name: {{.Name}}
    	UnitPrice: {{.UnitPrice}}
    	Quantity: {{.Quantity}}
    {{end}}`)

模板中的空白符号处理

{{-表示剔除模板内容左侧的所有空白符号,-}}表示剔除模板内容右侧的所有空白符号

tmpl, err := template.New("test").Parse(`Inventory
{{- with .Inventory}}
    SKU: {{.SKU}}
    Name: {{.Name}}
    UnitPrice: {{.UnitPrice}}
    Quantity: {{.Quantity}}
{{- end}}
`)

这里需要特别注意减号两侧的空格,如果没有使用空格将减号与模板中其它内容分开的话,会被模板引擎以为是表达式的一部分。例如,使用{{-with .Inventory}}则会报如下错误:

unexpected bad number syntax: "-w" in command
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值