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 gostudyimport ("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 stringAge  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 stringAge  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.rhkb.cn/news/498343.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优化租赁小程序提升服务效率与用户体验的策略与实践

内容概要 在这个快速发展的商业环境中&#xff0c;租赁小程序成为了提升服务效率和用户体验的重要工具。通过对用户需求的深入挖掘&#xff0c;我们发现他们对于功能的便捷性、响应速度和界面的友好性有着极高的期待。因此&#xff0c;针对这些需求&#xff0c;完善租赁小程序…

基础数据结构--二叉树

一、二叉树的定义 二叉树是 n( n > 0 ) 个结点组成的有限集合&#xff0c;这个集合要么是空集&#xff08;当 n 等于 0 时&#xff09;&#xff0c;要么是由一个根结点和两棵互不相交的二叉树组成。其中这两棵互不相交的二叉树被称为根结点的左子树和右子树。 如图所示&am…

shell学习变量(二)

这里写目录标题 一、概念1、环境变量2、本地变量3、系统变量 二、环境变量三、本地变量四、系统变量五、定义变量规则1、命名规则2、定义方式3、unset命令&#xff1a;删除变量 一、概念 1、环境变量 环境变量指的是再当前进程有效&#xff0c;并且能够被子进程调用&#xff…

自动驾驶3D目标检测综述(六)

停更了好久终于回来了&#xff08;其实是因为博主去备考期末了hh&#xff09; 这一篇接着&#xff08;五&#xff09;的第七章开始讲述第八章的内容。第八章主要介绍的是三维目标检测的高效标签。 目录 第八章 三维目标检测高效标签 一、域适应 &#xff08;一&#xff09;…

如何恢复永久删除的PPT文件?查看数据恢复教程!

可以恢复永久删除的PPT文件吗&#xff1f; Microsoft PowerPoint应用程序是一种应用广泛的演示程序&#xff0c;在人们的日常生活中经常使用。商人、官员、学生等在学习和工作中会使用PowerPoint做报告和演示。PowerPoint在人们的学习和工作生活中占主导地位&#xff0c;每天都…

四大自平衡树对比:AVL树、红黑树、B树与B+树

AVL树、红黑树、B树和B树的对比与应用场景 树系列相关文章&#xff08;置顶&#xff09; 1、从链表到平衡树&#xff1a;二叉查找树的退化与优化 2、自平衡二叉查找树&#xff1a;如何让二叉查找树始终保持高效 3、AVL树入门&#xff1a;理解自平衡二叉查找树的基础 4、红黑树全…

IOS safari 播放 mp4 遇到的坎儿

起因 事情的起因是调试 IOS 手机下播放服务器接口返回的 mp4 文件流失败。对于没调试过移动端和 Safari 的我来说着实费了些功夫&#xff0c;网上和AI也没有讲明白。好在最终大概理清楚了&#xff0c;在这里整理出来供有缘人参考。 问题 因为直接用 IOS 手机的浏览器打开页面…

Kubernetes Gateway API-2-跨命名空间路由

1 跨命名空间路由 Gateway API 具有跨命名空间路由的核心支持。当多个用户或团队共享底层网络基础设施时,这很有用,但必须对控制和配置进行分段,以尽量减少访问和容错域。 Gateway 和 Route(HTTPRoute,TCPRoute,GRPCRoute) 可以部署到不同的命名空间中,路由可以跨命名空间…

第十六届蓝桥杯模拟赛(第一期)(C语言)

判断质因数 如果一个数p是个质数&#xff0c;同时又是整数a的约数&#xff0c;则p称为a的一个质因数。 请问2024有多少个质因数。 了解 约数&#xff0c;又称因数。整数a整除整数b&#xff0c;b为a的因数&#xff08;约数&#xff09;质数&#xff0c;又称素数。只有1和它本身两…

AI安全的挑战:如何让人工智能变得更加可信

引言 随着人工智能&#xff08;AI&#xff09;技术在各个领域的广泛应用&#xff0c;尤其是在医疗、金融、自动驾驶和智能制造等行业&#xff0c;AI正在重塑我们的工作和生活方式。从提高生产效率到实现个性化服务&#xff0c;AI带来了前所未有的便利。然而&#xff0c;在享受这…

TiDB 的MPP架构概述

MPP架构介绍&#xff1a; 如图&#xff0c;TiDB Server 作为协调者&#xff0c;首先 TiDB Server 会把每个TiFlash 拥有的region 会在TiFlash上做交换&#xff0c;让表连接在一个TiFlash上。另外 TiFlash会作为计算节点&#xff0c;每个TiFlash都负责数据交换&#xff0c;表连接…

springboot499基于javaweb的城乡居民基本医疗信息管理系统(论文+源码)_kaic

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…

【SQL Server】教材数据库(1)

1 利用sql建立教材数据库&#xff0c;并定义以下基本表&#xff1a; 学生&#xff08;学号&#xff0c;年龄&#xff0c;性别&#xff0c;系名&#xff09; 教材&#xff08;编号&#xff0c;书名&#xff0c;出版社编号&#xff0c;价格&#xff09; 订购&#xff08;学号…

RT-Thread中堆和栈怎么跟单片机内存相联系

现在RT-ThreadMCU的应用方式越来越普遍&#xff0c;RT-Thread需要配置MCU中的RAM到的系统中&#xff0c;进入系统内存管理&#xff0c;才能提供给基于实时系统的应用程序使用&#xff0c;比如给应用程序提供malloc、free等函数调用功能。在嵌入式软件开发中&#xff0c;我们经常…

Linux硬盘分区 --- fdisk命令MBR分区、添加硬盘、lsblk命令

一、MBR分区 如果想对硬盘进行分区可以使用“ fdisk ”命令&#xff0c;它会采用MBR格式将硬盘进行分区。MBR是传统的分区机制&#xff0c;支持 32 位和 64 位系统&#xff0c;最多只能创建 4 个主分区&#xff0c;或者 3 个主分区和 1 个扩展分区&#xff0c;只支持不超过 2T…

GraphRAG 框架哪家强?选择最适合你智能问答系统的框架

GraphRAG 框架哪家强&#xff1f;选择最适合你智能问答系统的框架 点击进入&#xff1a;GraphRAG系列文章-Nano-GraphRAG&#xff1a;打造轻量级医疗诊断助手 点击进入&#xff1a;GraphRAG系列文章-突破传统知识管理瓶颈&#xff1a;LlamaIndex GraphRAG 让企业知识问答更智能…

day-102 二进制矩阵中的最短路径

思路 BFS 解题过程 从起点依次向八个方向尝试&#xff08;之后也一样&#xff09;&#xff0c;如果某个位置在矩阵内且值为0且没有访问过&#xff0c;将其添加到一个队列中&#xff0c;依次类推&#xff0c;直到到达出口 Code class Solution {public int shortestPathBinar…

vue3学习笔记(10)-$subscribe,store组合式写法

1.$subscribe订阅&#xff0c;监视vuex中数据得修改 2.localStorage里面穿的都是字符串&#xff0c;关掉浏览器数据还在 只能获取字符串&#xff0c;用ts语法写明&#xff0c;作为字符串使用 3.组合式写法

WAP短信格式解析及在Linux下用C语言实现

WAP短信格式解析及在Linux下用C语言实现 一、引言二、WAP短信格式概述三、WAP短信头的内容四、UDHI与WAP短信体的关系五、在Linux下用C语言解析WAP短信头及短信体内容一、引言 在移动通信领域,短信作为一种古老却稳定的通信方式,一直扮演着重要的角色。随着技术的发展,短信…

从 Coding (Jenkinsfile) 到 Docker:全流程自动化部署 Spring Boot 实战指南(简化篇)

前言 本文记录使用 Coding (以 Jenkinsfile 为核心) 和 Docker 部署 Springboot 项目的过程&#xff0c;分享设置细节和一些注意问题。 1. 配置服务器环境 在实施此过程前&#xff0c;确保服务器已配置好 Docker、MySQL 和 Redis&#xff0c;可参考下列链接进行操作&#xff1…