Go text/template详解:使用指南与最佳实践
I. 简介
A. 什么是 Go text/template
Go text/template 是 Go 语言标准库中的一个模板引擎,用于生成文本输出。它使用类似于 HTML 的模板语言,可以将数据和模板结合起来,生成最终的文本输出。
B. Go text/template 的优点
Go text/template 具有以下优点:
- 简单易用:使用类似于 HTML 的模板语言,易于学习和使用。
- 安全可靠:支持自动转义,避免了 XSS 攻击等安全问题。
- 高效性能:使用模板缓存和预编译技术,提高了渲染效率。
- 灵活可扩展:支持自定义函数和控制结构,可以满足各种需求。
C. Go text/template 的应用场景
Go text/template 可以用于生成各种类型的文本输出,例如 HTML、XML、JSON、Markdown、Golang 等。它适用于以下场景:
- Web 应用程序:可以用于生成动态网页、邮件模板、报表等。
- 命令行工具:可以用于生成文本报告、配置文件等。
- 数据处理:可以用于生成数据文件、日志文件等。
- 代码生成:用于动态生成代码等。
II. 模板语法
A. 变量
在 Go text/template 中,变量由双大括号 {{ 和 }} 包围,例如 {{.Name}} 表示一个名为 Name 的变量。变量可以是结构体、数组、切片、映射等类型,也可以是自定义类型。
- 变量定义
在模板中,可以使用{{$}}语句定义一个变量,如下所示:
{{$name :="qqxhb"}}
这个语句定义了一个名为"name"的变量,其值为"qqxhb"。在模板中,可以使用{{$变量名}}语句来引用这个变量,如下所示:
{{$name}}
这个语句会输出"qqxhb"。
- 变量赋值
在模板中,可以使用{{$}}语句给变量赋值,和定义的区别是没有冒号如下所示:
{{$name ="qqxhb"}}
这个语句将字符串"qqxhb"赋值给变量,然后使用{{$name}}输出变量的值,即"qqxhb"。
- 变量操作
在模板中,可以使用{{range}}语句遍历一个变量的值,如下所示:
{{range .Names}}{{.}}{{end}}
这个语句表示遍历"Names"变量的值,并输出每个值。
- 变量函数
在模板中,可以使用内置函数来操作变量,如下所示:
{{len .Names}}
这个语句表示获取"Names"变量的长度,并输出它的值。
Go text/template提供了丰富的变量操作功能,可以用于生成各种文本格式的输出。通过上述示例,可以更好地理解和掌握Go text/template中变量的使用方法。
B. 控制结构
Go text/template 支持多种控制结构,例如 if、range、with 等。这些控制结构可以用于条件判断、循环迭代、变量作用域等。if和range是两个非常常用的控制结构,下面是关于Go text/template中if和range的详细用法:
- if语句
if语句用于根据条件判断是否输出某个内容。if语句的语法如下:
{{if .Condition}}...{{end}}
其中,“.Condition"表示一个条件表达式,如果该表达式的值为true,则输出”…"中的内容。
示例:
{{if .Name}}Hello, {{.Name}}{{end}}
这个语句表示如果"Name"变量的值不为空,则输出"Hello, "和"Name"变量的值。
除了判断空这种场景,我们更多的可能是判断等和不等。在Go text/template 中用于等式与不等式判断的函数主要有以下六种(均接受两个,分别名为 arg1 和 arg2 的参数):
eq:当等式 arg1 == 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
示例:
{{if eq $age1 $age2}}年龄相同
{{else}}年龄不相同
{{end}}
或者是组合条件,如:
{{if and (eq $status 1) (ne $title "")}}上架
{{else}}下架
{{end}}
- range语句
range语句用于遍历一个数组、切片、映射或通道,并输出其中的每个元素。range语句的语法如下:
{{range .Array}}...{{end}}
{{range .Slice}}...{{end}}
{{range .Map}}...{{end}}
{{range .Channel}}...{{end}}
其中,“.Array”、“.Slice”、“.Map"和”.Channel"分别表示一个数组、切片、映射和通道。"…"中的内容表示遍历到的每个元素。
示例:
{{range .Names}}Hello, {{.}}!{{end}}
这个语句表示遍历"Names"变量的值,并输出"Hello, "和每个值。
遍历也支持两个参数,和go一样有索引遍历,如:
{{range $i, $name := .Names}}{{$i}}. {{$name}}
{{end}}
- with语句
在模板中,with语句用于设置当前上下文中的变量,下面是关于Go text/template中with的详细用法:
- with语句
with语句用于设置当前上下文中的变量,使得在该语句块中可以直接使用该变量。with语句的语法如下:
{{with .Variable}}...{{end}}
其中,“.Variable"表示一个变量,”…"中的内容表示在该语句块中可以直接使用该变量。
示例:
{{with .Person}}
Name: {{.Name}}
Age: {{.Age}}
{{end}}
这个语句表示设置当前上下文中的变量为"Person",并在该语句块中可以直接使用"Person"变量中的"Name"、"Age"等字段。
- with-else语句
with-else语句用于根据条件判断是否设置当前上下文中的变量。with-else语句的语法如下:
{{with .Variable}}...{{else}}...{{end}}
其中,“.Variable"表示一个变量,如果该变量的值不为空,则设置当前上下文中的变量为该变量,”…“中的内容表示在该语句块中可以直接使用该变量;否则输出"else"后面的”…"中的内容。
示例:
{{with .Person}}{{.Name}}{{else}}Unknown{{end}}
这个语句表示如果"Person"变量的值不为空,则设置当前上下文中的变量为"Person",并输出"Person"变量中的"Name"字段;否则输出"Unknown"。
C. 函数
Go text/template 内置了一些常用的函数,例如 len、range、printf 等。同时,也支持自定义函数,可以通过 Funcs() 方法注册自定义函数,或者是某个结构的方法。在模板中,函数是一种非常重要的元素,可以用于操作变量、格式化输出等。下面是关于Go text/template中函数的详细用法,包括自定义函数和结构体方法:
- 内置函数
Go text/template中内置了一些常用的函数,如下所示:
- len:返回一个字符串、数组、切片、映射或通道的长度。
- index:返回一个字符串、数组或切片中指定位置的元素。
- printf:根据格式字符串输出格式化的字符串。
- range:遍历一个数组、切片、映射或通道,并输出其中的每个元素。
- with:设置当前上下文中的变量。
示例:
{{len .Names}}
{{index .Names 0}}
{{printf "%d" .Age}}
{{range .Names}}{{.}}{{end}}
{{with .Person}}{{.Name}}{{end}}
这些语句分别表示获取"Names"变量的长度、获取"Names"变量中的第一个元素、格式化输出"Age"变量的值、遍历"Names"变量的值并输出每个值、设置当前上下文中的变量为"Person"并输出"Person"变量中的"Name"字段。
- 自定义函数
除了内置函数外,还可以自定义函数来操作变量、格式化输出等。自定义函数的语法如下:
{{funcName arg1 arg2 ...}}
其中,"funcName"表示函数名,“arg1”、"arg2"等表示函数的参数。
示例:
{{upper .Name}}
这个语句表示调用名为"upper"的自定义函数,将"Name"变量的值转换为大写字母并输出。
自定义函数需要在模板执行之前注册,可以使用text/template包中的Funcs方法来注册自定义函数,示例代码如下:
func upper(s string) string {return strings.ToUpper(s)
}t := template.New("test").Funcs(template.FuncMap{"upper": upper,
})
这个代码片段定义了一个名为"upper"的自定义函数,并将其注册到名为"test"的模板中。
- 结构体方法
除了自定义函数外,还可以使用结构体方法来操作变量、格式化输出等。结构体方法的语法如下:
{{.Variable.Method arg1 arg2 ...}}
其中,".Variable"表示一个变量,"Method"表示该变量的一个方法,“arg1”、"arg2"等表示方法的参数。
示例:
{{.Person.GetName}}
这个语句表示调用"Person"变量的"GetName"方法,并输出该方法的返回值。
结构体方法不需要在模板执行之前注册,只需要在结构体定义即可,然后用结构体作为模版参数,代码如下:
type Person struct {Name string
}func (p Person) GetName() string {return p.Name
}t := template.New("test")
t.Parse(&buf,&Person{})
这个代码片段定义了一个名为"Person"的结构体,并在该结构体中定义了一个名为"GetName"的方法。
D. 注释
在模板中,注释是一种非常重要的元素,可以用于注释模板中的代码,方便代码的维护和阅读。下面是关于Go text/template中注释的详细用法:
- 单行注释
单行注释用于注释一行代码,其语法如下:
{{/* This is a comment */}}
其中,"/“和”/"表示注释的开始和结束,"This is a comment"表示注释的内容。
示例:
{{/* This is a comment */}}Hello, {{.Name}}!
这个语句表示注释"Hello, {{.Name}}!"这一行代码。
- 多行注释
多行注释用于注释多行代码,其语法如下:
{{- /* This is a comment
on multiple lines */ -}}
其中,"{{- “和” -}}"表示注释的开始和结束,“This is a comment on multiple lines"表示注释的内容。需要注意的是,注释内容前后的空格会被保留,如果不想保留空格,可以在注释开始和结束标记中使用”-"符号。
示例:
{{- /* This is a comment
on multiple lines */ -}}
Hello, {{.Name}}!
这个语句表示注释"Hello, {{.Name}}!"这一行代码,并且注释内容跨越了多行。
III. 模板解析和渲染
A. 解析模板
使用 template.New() 函数创建一个新的模板对象,然后使用 Parse() 方法解析模板字符串。如果模板字符串中包含多个模板,可以使用 ParseFiles() 或 ParseGlob() 方法解析多个模板文件。
在Go语言中,使用text/template包创建和解析模板非常简单。下面是关于Go text/template模板创建和解析注释的详细用法:
在Go text/template中,可以使用New函数创建一个新的模板对象,示例代码如下:
t := template.New("test")
其中,"test"表示模板的名称,可以根据实际情况进行修改。
B. 渲染模板
使用 Execute() 方法渲染模板,并将结果输出到指定的 io.Writer 中。如果模板需要接收参数,可以将参数传递给 Execute() 方法。
err := t.Execute(os.Stdout, map[string]string{"Name": "World"})
其中,"os.Stdout"表示输出流,"map[string]string{“Name”: “World”}"表示模板中的变量。
C. 模板缓存
text/template 支持模板缓存,可以提高模板渲染的效率。使用 template.Must() 函数可以创建一个带有模板缓存的模板对象,如果解析模板失败,会直接 panic。
IV. 最佳实践
A. 模板设计原则
在设计模板时,应该遵循以下原则:
- 简洁明了:模板应该尽量简洁明了,避免过多的嵌套和复杂的控制结构。
- 可维护性:模板应该易于维护和修改,避免出现重复的代码和逻辑。
- 可扩展性:模板应该具有一定的扩展性,可以通过自定义函数和控制结构满足各种需求。
B. 模板性能优化
在优化模板性能时,应该注意以下几点:
- 使用模板缓存:使用 template.Must() 函数创建一个带有模板缓存的模板对象,可以提高模板渲染的效率。
- 避免重复解析:避免在每次渲染模板时都重新解析模板,可以将模板解析放在初始化阶段。
- 减少模板变量:减少模板中的变量数量,可以提高模板渲染的效率。
C. 模板安全性
在使用模板时,应该注意以下安全问题:
- 避免 XSS 攻击:使用自动转义功能,避免输出恶意脚本和标签。
- 避免注入攻击:避免将用户输入作为模板变量,可以使用模板函数进行转义和过滤。
V. 总结
Go text/template 是一个简单易用、安全可靠、高效性能、灵活可扩展的模板引擎,适用于生成各种类型的文本输出。在使用模板时,应该遵循最佳实践,注意模板设计原则、模板性能优化和模板安全性。
Tips: 欢迎评论区讨论,你想要的或者你知道的其他用法哦!!!
相关文章:
Go text/template详解:使用指南与最佳实践
I. 简介 A. 什么是 Go text/template Go text/template 是 Go 语言标准库中的一个模板引擎,用于生成文本输出。它使用类似于 HTML 的模板语言,可以将数据和模板结合起来,生成最终的文本输出。 B. Go text/template 的优点 Go text/templa…...

Stable Diffusion在各种显卡上的加速方式测试,最高可以提速211.2%
Stable Diffusion是一种基于扩散模型的图像生成技术,能够从文本生成高质量的图像,适用于CG,插图和高分辨率壁纸等领域。 但是它计算过程复杂,使得它的生成速度较慢。所以研究人员就创造了各种提高其速度的方式,比如Xf…...
Java读取外链图片忽略ssl验证转为base64
最近在对接外部接口时遇到返回的图片所在的服务器全都没有ssl证书,导致在前端直接用img标签展示时图片开裂。于是转为通过后端获取,绕过ssl验证之后转为base64返回。记录一下代码段。 package com.sy.ai.common.utils;import cn.hutool.core.codec.Base…...

系统架构设计师 10:软件架构的演化和维护
一、软件架构演化 如果软件架构的定义是 SA{components, connectors, constraints},也就是说,软件架构包括组件、连接件和约束三大要素,这类软件架构演化主要关注的就是组件、连接件和约束的添加、修改与删除等。 二、面向对象软件架构演化…...

Windows 11 绕过 TPM 方法总结,通用免 TPM 镜像下载 (2023 年 7 月更新)
Windows 11 绕过 TPM 方法总结,通用免 TPM 镜像下载 (2023 年 7 月更新) 在虚拟机、Mac 电脑和 TPM 不符合要求的旧电脑上安装 Windows 11 的通用方法总结 请访问原文链接:https://sysin.org/blog/windows-11-no-tpm/,查看最新版。原创作品…...

EXCEL,如何比较2个表里的数据差异(使用数据透视表)
目录 1 问题: 需要比较如下2个表的内容差异 1.1 原始数据喝问题 1.2 提前总结 2 使用EXCEL公式方法 2.1 新增辅助列: 辅助index 2.2 具体公式 配合条件格式 使用 3 数据透视表方法 3.1 新增辅助列: 辅助index 3.2 需要先打开 数据透视表向导 …...
字节抖音小程序,使用 uniapp 调起内置支付
字节抖音小程序,使用 uniapp 调起内置支付 第一步:提交订单 后端通过抖音预下单接口,提交支付订单信息。 预下单接口_小程序_抖音开放平台预下单接口 提交支付订单信息。 ## 使用限制 无 ## 接口说明 预下单接口需要保证同一app_id下每笔订…...
django模板继承和组件了解
1、模板继承 什么时候需要用到模板呢,比如我们在开发的页面的导航栏,你点不同的功能页面这个导航栏都是一样的,如果每个页面都要加上这个导航条会写重复代码,而且如果导航条有变化,每个页面都要修改,这个是…...
首屏优化,给以图片为背景的元素增加相似背景,优化用户体验,background-image 绘制规则
每日鸡汤:每个你想要学习的瞬间都是未来的你向自己求救 假设你的项目首页有个大大的图片作为背景,那么这个图片肯定会在网络不好的时候加载出来很慢,导致用户回看到一大片白屏,这样很影响体验。这也是老生常谈的首屏优化的问题。例…...

【用户体验分析报告】 按需加载组件,导致组件渲染卡顿,影响交互体验?组件拆包预加载方案来了!
首先,我们看一些针对《如何提升应用首屏加载体验》的文章,提到的必不可少的措施,便是减少首屏幕加载资源的大小,而减少资源大小必然会想到按需加载措施。本文提到的便是一个基于webpack 插件与 react 组件实现的一套研发高度自定义…...

idea 关闭页面右侧预览框/预览条
idea 关闭页面右侧预览框 如图,预览框存在想去除 找了好多方法,什么去掉“setting->appearance里的show editor preview tooltips”的对钩;又或者在该预览区的滚动条上右键,“取消勾选show code lens on scrollbar hover”。都…...

CSS3 Flexbox
Flex 是 Flexible Box 的缩写,意为弹性盒子布局。 CSS3中一种新的布局模式:W3C在2009年提出的一种布局方案,一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。其目的是提供一种更加有效的方式来对一个容器…...

东南大学轴承故障诊断(Python代码,CNN模型,适合复合故障诊断研究)
运行代码要求: 代码运行环境要求:Keras版本>2.4.0,python版本>3.6.0 本次实验主要是在两种不同工况数据下,进行带有复合故障的诊断实验,没有复合故障的诊断实验。 实验结果证明,针对具有复合故障的…...
ubuntu--Motrix
Motrix官网 https://motrix.app/ 适用于windows和ubuntu 资源链接 链接: https://pan.baidu.com/s/16ka-w30BXJn066absXJXCA 密码: cds2 下载上面的资源,打开终端,安装Motrix sudo dpkg -i XXX.deb 在ubuntu安装好chrome,然后打开设置中…...

PHP 3des加解密新旧方法可对接加密
一、旧3des加解密方法 <?php class Encrypt_3DES {//加密秘钥,private $_key;private $_iv;public function __construct($key, $iv){$this->_key $key;$this->_iv $iv;}/*** 对字符串进行3DES加密* param string 要加密的字符串* return mixed 加密成…...
【朴素贝叶斯-新闻主题分类】
朴素贝叶斯对新闻进行分类 朴素贝叶斯算法是一种常用的文本分类方法,特别适用于自然语言处理任务,如新闻分类。在这篇博客中,我们将使用Python的scikit-learn库来实现朴素贝叶斯算法,并将其应用于新闻分类任务。 数据准备 首先…...
安卓面试问题记录
目录 1. JNI和NDK1.谈谈你对JNI和NDK的理解2.简要的JNI调用过程:2. 线程、同步、异步1.Java创建线程的方式有几种?start()方法和 run()方法的区别2.Handler 机制和原理3.为什么在子线程中创建Handler会抛异常?4.Android中的ANR的解决方法5.intentservice有什么优点?6.okhtt…...

php-golang-jsonrpc2.0 rpc-codec/jsonrpc2和tivoka/tivoka实践
golang代码: package main import ( "context" "net" "net/rpc" "github.com/powerman/rpc-codec/jsonrpc2" ) type App struct{} type Res struct { Code int json:"code" Msg string json:"msg&quo…...
听力词汇笔记(6级)
2022年9月六级 1.personality traits:人格特征 2.all of this notwithstanding:尽管如此 3.come under:受到 4.scrutiny:关注 5.highly responsive to:对....高度敏感 6.preteen year:青春期前 7.susceptible to:受....影响 8.take sharp preced…...

【JVM】详细解析java创建对象的具体流程
目录 一、java创建对象的几种方式 1.1、使用new关键字 1.2、反射创建对象 1.2.1、Class.newInstance创建对象 1.2.2、调用构造器再去创建对象Constructor.newInstance 1.3、clone实现 1.4、反序列化 二、创建对象的过程 2.1、分配空间的方式 1、指针碰撞 2、空闲列表 …...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...