当前位置: 首页 > article >正文

Go-知识 模板

Go-知识 模板

  • 1. 介绍
  • 2. Text/template 包
  • 3. Html/template 包
  • 4. 模板语法
    • 4.1 模板标签
    • 4.2 添加注释
    • 4.3 访问变量
    • 4.4 访问方法
    • 4.5 模板变量
    • 4.6 访问函数
    • 4.7 数据渲染
    • 4.8 条件判断
    • 4.9 循环遍历
    • 4.10 嵌入子模板
    • 4.11 局部变量
    • 4.12 输出字符串
    • 4.13 预定义的全局函数
    • 4.14 比较函数

1. 介绍

fmt.Printf可以做到格式化输出,这对于简单的例子已经足够,但是有时候还需要更加复杂的输出格式,甚至需要将格式与代码分离开来。这个时候就可以使用模板(Template)。

2. Text/template 包

text/template包提供了处理文字模板与数据的功能,模板引擎。

所谓模板引擎,就是将模板和数据进行渲染的输出格式化后的字符串程序。

使用模板引擎分为三步:

  1. 创建模板对象
  2. 加载模板
  3. 执行渲染模板

比如如下例子:

package gostudy

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

func TestTe(t *testing.T) {

	templ := `
{{range.}}--------------------------------------
Name:  {{.Name}}
Age:   {{.Age}}
{{end}}
`
	tp := template.Must(template.New("templ").Parse(templ))
	type Person struct {
		Name string
		Age  int
	}
	persons := []Person{
		{"gw", 18},
		{"lx", 20},
		{"ly", 21},
	}
	if err := tp.Execute(os.Stdout, persons); err != nil {
		t.Log(err)
	}
}

执行结果如下

请添加图片描述

在代码中, templ 就是一段模板文字,然后使用程序中的数据,渲染模板,填充模板中的占位,最后得到完整的输出。

除了将模板文字在程序中写死,也可以将模板与程序分离,也就是格式和数据分离,使用不同的文件存储

首先创建一个文件用于存储模板文字,后缀可以自定义

在这里插入图片描述

然后在程序中直接加载模板文件

func TestTeTxt(t *testing.T) {
	tp := template.Must(template.ParseFiles("./name_age.tpl"))
	type Person struct {
		Name string
		Age  int
	}
	persons := []Person{
		{"gw", 18},
		{"lx", 20},
		{"ly", 21},
	}
	if err := tp.Execute(os.Stdout, persons); err != nil {
		t.Log(err)
	}
}

执行结果与之前完全相同

如果要加载多个模板文件,有两种方式:枚举方式,正则方式 以及目录方式

枚举方式 tp := template.Must(template.ParseFiles("./name_age1.tpl", "./name_age2.tpl","./name_age3.tpl"))

正则方式 tp := template.Must(template.ParseGlob("./*.tpl"))

目录方式

	files, err := filepath.Glob("./*.html.tmpl")
	if err != nil {
		log.Fatalf("Error while globbing files: %v", err)
	}
	tp := template.Must(template.ParseFS(os.DirFS("./)"), files...))

template.Must 主要是检测模板是否正确。

3. Html/template 包

text/template类似,html/template主要提供支持 HTML 模板的功能,使用方法差不多。

创建一个index.html.tmpl 文件

在这里插入图片描述

模板内容如下

<!doctype html>
  <head>
    <meta charset="UTF-8">
    <meta name="Author" content="">
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    <title>Go</title>
  </head>
  <body>
    {{.}}
  </body>
</html>

然后创建一个web服务端

func TestHt(t *testing.T) {
	tp := template.Must(template.ParseFiles("./index.html.tmpl"))

	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		tp.Execute(writer, "Hello")
	})
	http.ListenAndServe(":8080", nil)

}

访问

在这里插入图片描述

在多模板的时候,可以定义模板的名字,然后在执行的时候,指定模板渲染

比如

在这里插入图片描述

使用 {{ define "index"}} 定义了模板的name

然后加载模板的时候,加载全部的模板,指定index1 执行

func TestHt(t *testing.T) {
	files, err := filepath.Glob("./*.html.tmpl")
	if err != nil {
		log.Fatalf("Error while globbing files: %v", err)
	}
	tp := template.Must(template.ParseFS(os.DirFS("./"), files...))
	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		tp.ExecuteTemplate(writer, "index1", "Hello")
	})
	http.ListenAndServe(":8080", nil)
}

执行并访问

在这里插入图片描述

同时在模板文件之间可以进行嵌套

比如如下模板

在这里插入图片描述

然后修改index1.html.tmpl

在这里插入图片描述

重启web

在这里插入图片描述

4. 模板语法

4.1 模板标签

{{}} 就是模板标签,中间是模板的语法内容。

4.2 添加注释

{{/* 注释 */}}, 使用 {{/**/}} 包含注释的内容。

    2. 注释 `{{/* 注释 */}}`: <br/>
    {{/* 这是一条注释 */}}
    <br/>

4.3 访问变量

{{.}} 此标签输出当前对象值。

{{.Name}} 表示输出对象中字段或方法名为 Name 的值。

需要注意,如果方法定义为 func (p Person)Name() string 那么,在渲染模板的时候,一定是值对象。

如果方法定义为 func (p *Person)Name() string 那么,在渲染模板时,一定是指针对象。

如果 Name 是匿名字段,那么还可以继续访问内部字段,比如 {{.Name.First}}

如果存在一个方法Say,并且是 Name 的方法。

假设Say返回对象,那么可以继续访问{{.Name.Say.Field}}

{{.F1.F2.F3}},F 可以是方法也可以是结构体。(要小心空指针)

    1. 输出当前对象的值 `{{ . }}` : <br/>
    {{ . }}
    <br/>
        3. 变量: <br/>
      3.1 当前对象 `\{\{ . \}\}` : {{ . }} <br/>
          属性 NameStr : {{ .NameStr }} <br/>
      3.2 方法 `\{\{ .Name \}\}` : {{ .Name }} <br/>
      3.3 定义变量 `\{\{ $x := "test" \}\}` : {{ $x := "test" }} <br/>
      3.4 访问变量 `\{\{ $x \}\}` : {{ $x }} <br/>
      3.5 定义变量 n , 接收当前对象的值,然后传递给 ForName 函数,返回 对象并打印输出: <br/>
          `\{\{ $n := .NameStr \}\}`,`\{\{ .ForName $n \}\}` <br/>
          实际上等价于 `\{\{ .ForName \}\}` <br/>
          {{ $n := .NameStr }} <br/>
          {{ $n }} <br/>
          {{ .ForName $n }} <br/>
          {{ .ForName .NameStr }} <br/>

在这里插入图片描述

4.4 访问方法

{{.Method param1 param2 param3}} 调用方法 Method,后面的 param是调用参数

4.5 模板变量

在模板中定义变量,变量名称用字母和数据组成,并加上 $ 前缀,采用简短赋值。

比如 {{ $x := "OK" }}, {{ $y := "yes"}}

访问定义的模板变量

{{ $x }} 用于输出在模板中定义的名称为 x 的变量,当 定义的变量是个结构体的时候,可以连续访问

4.6 访问函数

  • 函数:在 Go 中,函数是独立的,必须显式地注册到模板中,以便在模板中使用。
  • 方法:方法是与特定类型(如结构体)关联的。当你在模板中使用结构体的实例时,模板引擎会自动识别该实例的方法。

在模板中要使用函数,必须先注册,不注册的话,是不能使用的

{{ FuncName1 }} 调用标签名字为 FuncName1 的函数,等价于执行 FuncName1()

{{ FuncName1 param1 param2 ..}} 调用带有参数的函数

{{ FuncName1 . }} 等价于 FuncName1(this),这里的 this 取决于传递给模板渲染时的数据。

{{ .|FuncName1 }}{{ FuncName1 . }}

      3.6 访问函数 `\{\{ SayName .NameStr \}\}`: {{ SayName .NameStr }} <br/>
      3.7 访问函数 `\{\{ .|Say  \}\}` : {{ .|Say }} <br/>
          访问函数 `\{\{ Say . \}\}` : {{ Say . }} <br/>

在这里插入图片描述

4.7 数据渲染

在模板渲染的时候,如果想使用复杂的数据结构或者需要渲染很多数据,那么可以使用复杂struct 或者map进行传递。

如果使用map

	data := map[string]interface{}{
		"NameStr": "xiaomei",
		"Age":     18,
		"Country": "China",
	}

模板

<h1>{{ SayHello .NameStr }}!</h1>
<p>Age: {{ .Age }}</p>
<p>Country: {{ .Country }}</p>

使用struct通常更具可读性和类型安全,而使用 map 则提供了更大的灵活性。

4.8 条件判断

{{ if condition }} T1 {{ end }} 结构为 {{ if ... }} ... {{ end }},类似go里面单个 if

{{ if condition }} T1 {{ else }} T2 {{ end }}结构为{{ if ... }} ... {{ else }} ... {{ end }},类似 go 里面的 if-else

{{ if condition }} T1 {{ else if con2}} T2 ... {{ else }} Tn {{ end }} 类似go 里面的多if分支

if 后面可以是一个条件表达式,条件可以是调用函数,方法等等,也可以是一个字符串变量或者布尔值变量。

当是字符串变量时,空字符串为 false,非空为true。

    4. 条件 <br/>
      Sex = {{ .Sex }}, Age = {{ .Age }} <br/>
      单个 if : {{ if eq .Sex "woman" }}
                 女
               {{ else }}
                 男
               {{ end }}
                <br/>
      多个 if :
      {{ if and  (eq .Sex "woman") (le .Age 18 ) }}
        少女
      {{ else if and (eq .Sex "man") (le .Age 18 ) }}
        少男
      {{ else }}
        其他
      {{ end }}

在这里插入图片描述

4.9 循环遍历

{{ range $k,$v := .Var }} T {{ end }} range … end 结构内部如果要使用外部的变量,需要在外部变量的名字前加 $

{{ range .var }} {{ . }} {{ end }} 将遍历值直接展示出来

{{ range condition }} T {{ else }} TT {{ end }} 当没有可遍历的值的时候,执行 else 部分

5. 循环遍历 <br/>
      遍历数组直接输出<br/>
      {{ range .Msg }}
        {{ . }} ,
      {{ end }}
      <br/>
      遍历map输出<br/>
      {{ range .MsgMap }}
        {{ . }}
      {{ end }}
      <br/>
      遍历输出 k,v <br/>
      {{ range $k,$v := .MsgMap }}
        ( {{ $k }} , {{ $v }} ) <br/>
      {{ end }}
      <br/>
      定义外部变量 {{ $t := "say:" }} <br/>
      使用外部变量 <br/>
      {{ range $k,$v := .MsgMap }}
        {{ $t }} : {{ $k }} => {{ $v }} <br/>
      {{ end }}
      <br/>
      带有条件的循环遍历<br/>
      {{ range $k, $v := .MsgMap }}
        {{ if le $v 3 }}
          {{ $k }} => {{ $v }} <br/>
        {{ else }}
          ({{$k}},{{$v}})<br/>
        {{ end }}
      {{ end }}
      <br/>

输出

在这里插入图片描述

4.10 嵌入子模板

{{ template "name"}} 嵌入名称为 “name” 的子模板。 使用前必须使用 {{ define "name"}}{{ end }} 进行定义

{{ define "div" }}
<div>
 <b> World </b>
</div>
{{ end }}
    6. 子模板 <br/>
      {{ template "div" }}

在这里插入图片描述

子模板可以嵌套多次,嵌套多个

4.11 局部变量

{{ with ...}} T {{ end }} 将值赋值给标签内部的 .

{{ with ...}} T {{ else }} TT {{end}} 如果值为空,执行 else

7. 局部变量 <br/>
      {{ with .NameStr }}
        nameStr = {{ . }}<br/>
      {{ end }}
      <br/>
      带有 else 的 with <br/>
      {{ with "" }}
        不空
      {{ else }}
        空
      {{ end }}
      <br/>

在这里插入图片描述

4.12 输出字符串

{{ "\"output\""}} 转义输出

` 可以使字符串原样输出

{{ pintf "%q" "output"}} 函数调用输出 等价于 printf("%q", "output")

{{ "output"|printf "%q"}} 另一种调用方式 printf("%q","output")

{{ printf "%q" (print "out" "put")}} 多层调用 printf("%q", print("out","put"))

{{ "put" | print "%s%s" "out" | printf "%q"}} 另一种写法printf("%q", print("%s%s", "out","put"))

{{ "output" | prinf "%s" | printf "%q"}} 等价于 printf("%q", printf("%s", "output"))

{{ with "output"}} {{ printf "%q" .}} {{ end }} 使用 .的with 写法

{{ with $x := "output" | printf "%q"}} {{ $x }} {{ end }} 使用通道的with写法

{{ with $x := "output"}} {{ $x | printf "%q"}} {{ end }} 另一种写法

8. 字符串<br/>
      {{ "\"output\"" }} <br/>
      {{ `"output"` }} <br/>
      {{ `{{ printf "%q" "output" }}` }} {{ printf "%q" "output" }}<br/>
      {{ with "output" }} {{ . | printf "%q" }} {{ end }} <br/>

在这里插入图片描述

4.13 预定义的全局函数

{{ and x y}} 如果 x 为真,返回 y,否则返回 x

{{ or x y }} 如果 x 为真,返回x ,否则返回 y

{{ call func param1 param2 ...}} 调用函数,函数返回值限定为 1个或者2个(第二个必须是 error)

如果传递的参数与函数定义的不匹配,或者返回的 error 不为 nil ,停止执行

{{html}} 转义文本中的 html 标签

{{ index map 1 2 3}} 返回 index 后面的第一个参数的某个索引对应的元素值,其余参数作为索引值。必须是 map,数组,slice

{{ js }} 返回用 javascript 的 escape 处理后的文本

{{ len x }} 返回长度

{{ not x}} 取反

{{ print }} fmt.Sprint 的别名

{{ printf }} fmt.Sprintf 的别名

{{ println }} fmt.Sprintln的别名

{{ urlquery }} 在URL查询中嵌入到形参中的文本转义,类似 urlencode

    9. 预定义<br/>
    			<p>and: {{ and true "Y" }}</p>
    			<p>or: {{ or false "Y" }}</p>
    			<p>len: {{ len .Msg }}</p>
    			<p>not: {{ not false }}</p>
    			<p>print: {{ print "Hello, " "World!" }}</p>
    			<p>printf: {{ printf "Hello, %s!" "World" }}</p>
    			<p>println: {{ println "Hello," "World!" }}</p>
    			<p>index: {{ index .MsgMap "two" }}</p>
    			<p>call: {{ call .SayN "xiaomei" }}</p>

在这里插入图片描述

4.14 比较函数

{{ eq arg1 arg2}} :=> arg1 == arg2

{{ ne arg1 arg2 }} :=> arg1 != arg2

{{ lt arg1 arg2 }} :=> arg1 < arg2

{{ le arg1 arg2 }} :=> arg1 <= arg2

{{ gt arg1 arg2 }} :=> arg1 > arg2

{{ ge arg1 arg2 }} :=> arg1 >= arg2

比较函数对任何零值返回 false ,非零值返回 true 。

比较函数每次只接受两个参数

{{ eq arg1 arg2 arg3 arg4}} 等价于 arg1 == arg2 || arg1 == arg3 || arg1 == arg4


http://www.kler.cn/a/459576.html

相关文章:

  • MLP、CNN、Transformer 的区别解析
  • 【MATLAB第111期】基于MATLAB的sobol全局敏感性分析方法二阶指数计算
  • 数据库入门级SQL优化
  • Linux基础 -- pthread 设置线程调度示例
  • AI知识库与用户行为分析:优化用户体验的深度洞察
  • Linux(14)——网络管理
  • LLM常见面试题(31-35题)--深度学习基础概念
  • 计算机网络-L2TP Over IPSec基础实验
  • 【运维】部署Gitea
  • 目标检测入门指南:从原理到实践
  • Redis 安装部署[主从、哨兵、集群](windows版)
  • 爆改RagFlow
  • 【UE5】UnrealEngine源码构建3:启动UE5工程
  • 二、AI知识(神经网络)
  • 210.xxl-job定时任务:架构,可视化,GLUE模式,负载均衡,分片
  • Springboot(五十六)SpringBoot3集成SkyWalking
  • K8S-LLM:用自然语言轻松操作 Kubernetes
  • GPU 进阶笔记(四):NVIDIA GH200 芯片、服务器及集群组网
  • SpringSecurity 3.0.2.2版本
  • PostgreSQL的一主两从集群搭建部署 (两同步)
  • linux-headers-generic 依赖于 linux-headers-6.8.0-51-generic;然而:
  • Web安全 - “Referrer Policy“ Security 头值不安全
  • open_cv小练习
  • html+css+js网页设计 美食 美食4个页面带js
  • CentOS7 初始化模板
  • Matlab环形柱状图