gin框架 HTML 模板加载,渲染 使用详解和总结

gin框架中默认的HTML模板渲染使用  LoadHTMLGlob() 或者 LoadHTMLFiles() , 这个地方如果是使用的LoadHTMLGlob() 这个方法的话是有坑的,即当你的模板文件放在不同的文件夹中时,使用这个方式加载会将文件夹也作为文件加载进去,从而直接在模板渲染的时候抛异常!! 

假设在我们的项目templates文件夹中有如下结构的模板文件:

├── article
│   ├── detail.html
│   └── index.html
├── footer.html
├── header.html
├── index.html
└── search├── detail.html└── index.html

r := gin.Default()

LoadHTMLGlob模板加载匹配模式

 r.LoadHTMLGlob("templates/*.html")    如果是这种模式就只能加载顶层的3个html文件,子目录中的文件无法加载

 r.LoadHTMLGlob("templates/**/*.html")   这种方式就只能加载子目录article, search中一共4个文件

r.LoadHTMLGlob("template/**/*")  这种模式 只能加载子目录中的所有文件或者文件夹,顶层的3个模板无法加载

r.LoadHTMLGlob("template/**")  这种模式 可以加载所有的文件和目录(坑,模板编译时直接报异常, 不能使用这种方式!)

上面的4种方式加载模板对于我们上面的模板结构都不可用,直接抛弃! 

上面的方式只能适用于没有子目录的模板加载

filepath.WalkDir  + LoadHTMLFiles() 的方式加载模板

对于我们上面的模板结构只能采用LoadHTMLFiles()方式加载了, 使用这个方式加载,我们需要先自己加载我们需要的模板文件, 这个就需要使用filepath.WalkDir 这个目录遍历大杀器出场了。废话补多少直接删代码:

// 模板文件加载var tplFiles []stringfilepath.WalkDir("templates", func(path string, d fs.DirEntry, err error) error {if !d.IsDir() && strings.HasSuffix(d.Name(), ".html") {// 非目录,且是.html结尾的文件加入到模板文件列表tplFiles = append(tplFiles, path)}return nil})r.LoadHTMLFiles(tplFiles...) // 加载html模板

 在gin控制器中通过.HTML方法使用模板

这个非常简单直接用HTML方法即可。 需要注意的是这里的模板名称是很讲究的,我们来看一下这个HTML方法的原型: func (c *gin.Context) HTML(code int, name string, obj any)   

这里第一个参数是http的状态码一般都是200即可, 第二个参数name 就是我们要渲染的模板的名称,这里的名称默认是你加载的文件的不区分目录的文件名, 由于默认不区分目录,所以如果你有多个同名的文件,则必须在对应的文件中使用 define对文件名进行定义,如: {{ define "index.html"}}   你的模板内容  {{end}}   。  如果你加载的文件名每个都是唯一的,则不需要定义也可以直接使用。


r.GET("/index", func(c *gin.Context) {// 注意这里的第二个参数 模板名是很有讲究的c.HTML(http.StatusOK, "index.html", gin.H{"title": "Main website",})
})
r.Run(":8080")

html模板文件示例和模板包含命名定义使用示例

index.html 示例:

注意,由于index.html文件名称有重复,所以这里我们必须使用define对文件名进行定义,否则index.html加载的就可能不是你期望的文件!!!

另外这里我们使用内置函数 template 对另外2个公共的模板文件进行加载。 {{template "xxx.html" .}}

{{define "index.html"}}
<!DOCTYPE html>
<html><head>{{template "header.html" .}}</head><body><div class="container-fluid"><H1>Hello Gin HTML</H1><!--- footer --->{{template "footer.html" .}}</div></body>
</html>
{{end}}

head.html

这个head.html文件名是唯一的,所以不需要是哟共define定义也可使用, 注意这里的标题 {{.title}} 这个直接使用了 c.HTML方法的第三个参数中传递的动态变量

<meta charset="utf-8" />
<metaname="viewport"content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<title>{{.title}}</title>

footer.html

<!--- footer --->
<footer style="height: 100px; background: #1b1c1d"><div style="text-align: center; font-size: 14px; padding-top: 50px">By<a href="http://dev.tekin.cn" target="_blank">{{.title}}</a></div>
</footer>

article/index.html文件内容

注意这里的define定义的文件名 {{ define "article/index.html"}}   我们一般以当前文件所在的模板文件夹下的相对路径来命名。 在c.HTML里面使用的时候我们就使用 c.HTML(200, "article/index.html", nil) 即可。

{{ define "article/index.html"}}
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Article index</title><link rel="stylesheet" href="">
</head>
<body><h1>Hello my article</h1>
</body>
</html>{{end}}

自定义模板渲染器

你可以使用自定义的 html 模板渲染

import "html/template"func main() {router := gin.Default()html := template.Must(template.ParseFiles("file1", "file2"))router.SetHTMLTemplate(html)router.Run(":8080")
}

自定义分隔符

r.Delims("{[{", "}]}") // 自定义模板分隔符 这个一般情况下我们保持默认即可

自定义模板功能

这个就是使用.SetFuncMap加载我们自定义的函数进去就可以。 推荐在c.HTML里面绑定对象的方式调用对象方法更方便,调用方式为 将函数名换为   对象名.方法名

import ("fmt""html/template""net/http""time""github.com/gin-gonic/gin"
)func formatAsDate(t time.Time) string {year, month, day := t.Date()return fmt.Sprintf("%d/%02d/%02d", year, month, day)
}func main() {router := gin.Default()router.Delims("{[{", "}]}")router.SetFuncMap(template.FuncMap{"formatAsDate": formatAsDate,})router.LoadHTMLFiles("templates/index.html")router.GET("/raw", func(c *gin.Context) {c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),})})router.Run(":8080")
}

在模板中使用我们自定义的函数:

Date: {[{.now | formatAsDate}]}   这个是使用管道符 | 方式,

也可以这样使用  Date: {[{formatAsDate  .now }]}  如果是多个参数用空格分开即可。

 附录 go内置的默认模板函数

func builtins() FuncMap {return FuncMap{"and":      and,"call":     call,"html":     HTMLEscaper,"index":    index,"slice":    slice,"js":       JSEscaper,"len":      length,"not":      not,"or":       or,"print":    fmt.Sprint,"printf":   fmt.Sprintf,"println":  fmt.Sprintln,"urlquery": URLQueryEscaper,// Comparisons"eq": eq, // =="ge": ge, // >="gt": gt, // >"le": le, // <="lt": lt, // <"ne": ne, // !=}
}

gin框架HTML渲染使用总结:

1. gin框架中渲染模板必须要先加载,如果模板文件中没有子目录可以使用 LoadHTMLGlob() ,如果有子目录推荐使用 filepath.WalkDir  + LoadHTMLFiles() 的方式加载模板;

2. 模板名称默认为加载的文件的忽略目录的文件名, 如果有多个同名文件,则默认使用功能的是第一个加载的模板文件;

3. 在模板中包含其他模板可以使用template函数进行加载包含,即 {{template "xxx.html" .}}

4. gin中模板渲染使用c.HTML方法,这个方法有3个参数,第一个是http状态码,第二个是模板名称,第三个是要传递给模板的变量数据, 这个我们一般使用map数据结构

5. 自定义模板函数实际上就是将自己定义的函数使用 r.SetFuncMap(template.FuncMap{ "模板中使用的函数名": 函数名,})

6. 一般情况下我们可以通过在c.HTML的第三个参数里面绑定一个对象来代替自定义函数, 直接在模板中调用对象的方法更加方便和简洁,不需要另外绑定函数即可使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/35995.shtml

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

相关文章

G882磁力仪拖鱼位置是如何计算的?

根据参考文献&#xff0c;磁力仪拖鱼位置计算有两种方法&#xff1a; 1、直线法 直线计算法是假设不考虑海流、船摆等动态因素的影响&#xff0c;拖鱼与拖点始终和航向相同&#xff0c;即整个拖拽系统与船舶是刚性连接。 2、曲线法 实际海洋磁力测量中&#xff0c;在海风、海…

TP8 JS(html2canvas) 生成二维码并与背景图、文字组合生成分享海报

方法一&#xff1a;前端JS生成(推荐) 注意&#xff1a; 这个网页只能截图图片效果代码&#xff0c;其它任何html效果都不能有&#xff0c;不然截图就不准确 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><t…

Windows宝塔面板部署ThinkPHP8.0创建Vue项目案例

安装ThinkPHP8.0 登录宝塔面板&#xff0c;创建一个站点。 输入composer代码&#xff0c;执行完成后自动创建TP目录 composer create-project topthink/think tp 网站目录设置为tp&#xff0c;运行目录设置为public 设置PHP版本为8.0以上&#xff0c;不然会出现下面的报错代…

软考 有向图 数据库之关系模式范式

假设有一个关系 R(A, B, C, D)&#xff0c;并且已知以下函数依赖&#xff1a; A → B B → C BC → D 求候选键? 求候选码? 候选键/候选码 是同一个概念. 数据库范式也分为1NF,2NF,3NF,BCNF,4NF,5NF。 https://cloud.tencent.com/developer/article/2055118 2NF在1NF的基础…

低代码平台技术及其在CRM系统中的应用

随着信息技术的飞速发展&#xff0c;企业对于高效、灵活、可定制的软件开发需求日益增长。在这一背景下&#xff0c;低代码平台&#xff08;Low-Code Platform, LCP&#xff09;技术应运而生&#xff0c;并以其快速开发、易于维护和高度定制化的特性&#xff0c;逐渐成为企业信…

visual studio 2022配置和使用protobuf

上图证明&#xff0c;我真的测了好多遍&#xff0c;测了好多版本的protobuf&#xff0c;花了很多时间。不过好在最后在vs2022上测通了。 下载protobuf 这里是protobuf下载的地址。 Releases protocolbuffers/protobuf GitHub 个人使用的3.21.9这个版本才跑通的。 1、首先…

FastAPI-Body、Field

参考&#xff1a;模式的额外信息 - 例子 - FastAPI 在FastAPI中&#xff0c;Body和Field是两个常用的注解&#xff0c;它们用于定义请求体中的数据或路径参数、查询参数等的处理方式。这两个注解都来自于Pydantic库&#xff0c;用于数据验证和解析&#xff0c;但它们的应用场景…

第6章_libmodbus使用

文章目录 第6章 libmodbus使用6.1 libmodbus开发库6.1.1 功能概要6.1.2 源码获取6.1.3 源码阅读1. 新建工程2. 同步文件3.打开工程4. 操作示例5. 快捷键 6.1.4 libmodbus与应用程序的关系 6.2 libmodbus源代码解析6.2.1 核心函数6.2.2 框架分析与数据结构6.2.3 情景分析1. 初始…

OOXML入门学习

进入-飞入 <par> <!-- 这是一个并行动画序列的开始。"par"代表并行&#xff0c;意味着在这个标签内的所有动画将同时开始。 --><cTn id"5" presetID"2" presetClass"entr" presetSubtype"4" fill"hold&…

vue3 封装获取文件后缀和name的工具方法以及本地下载方法

获取文件后缀 /*** description&#xff1a;获取附件后缀* param {*} file 文件名称* param {*} isDot 是否显示点 0: 显示 1: 不显示*/ export const getFileType: (file?: string, isDot?: 0 | 1) > string (file, isDot 0) > {if (!file) {throw "file is n…

深度解析:Transformer自注意力机制的计算奥秘

深度解析&#xff1a;Transformer自注意力机制的计算奥秘 在自然语言处理&#xff08;NLP&#xff09;的广阔天地中&#xff0c;Transformer模型犹如一颗璀璨的星辰&#xff0c;以其卓越的性能照亮了序列建模的道路。而这一切&#xff0c;都离不开自注意力机制&#xff08;Sel…

C语言指针速成下篇

c语言的指针下篇终于迎来了收尾&#xff0c;那么废话不多说&#xff0c;我们直接进入正题 指针访问数组 # include <stdio.h> int main () { int arr[ 10 ] { 0 }; // 输⼊ int i 0 ; int sz sizeof (arr)/ sizeof (arr[ 0 ]); // 输⼊ int * p arr //这…

在Tomcat中部署war包

1、准备war包 确保已经有一个有效的war包&#xff0c;该war包包含了web应用程序的所有内容&#xff1b; 2、停止tomcat服务器 在部署之前&#xff0c;确保tomcat服务器已经停止&#xff0c;进入tomcat的配置目录执行命令&#xff1a;[路径]/tomcat/conf&#xff1b; 在Linux…

Socket——向FTP服务器发送消息并获得响应

1、简介 Socket&#xff08;套接字&#xff09;是网络编程中用于描述IP地址和端口的一个抽象概念&#xff0c;通过它可以实现不同主机间的通信。套接字可以分为几种不同的类型&#xff0c;每种类型对应不同的协议和传输模式。 1.1、基本概念 IP地址&#xff1a;用于标识网络…

【管理咨询宝藏137】RB大型卡车集团供应链体系优化设计方案中期汇报

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏137】RB大型卡车集团供应链体系优化设计方案中期汇报 【格式】PDF版本 【关键词】罗兰贝格、供应链管理、运营提升 【核心观点】 - 甲方采取销售…

每天一个项目管理概念之SOW

在项目管理中&#xff0c;Statement of Work&#xff08;SOW&#xff0c;工作说明&#xff09;是定义项目范围、目标、交付成果、时间表和预算的正式文档。 SOW的核心要素 SOW应当包含以下关键组成部分&#xff1a; 项目背景与目标 阐述项目的背景信息、发起原因以及预期达…

CBSD创建和管理bhyve容器Ubuntu@FreeBSD

bhyve介绍&#xff1a;bhyve&#xff1a;FreeBSD下的原生虚拟机管理器_freebsd 虚拟化平台bhyve-CSDN博客 两个bhyve的管理软件&#xff1a;使用bvm管理bhyve虚拟机管理系统FreeBSD-CSDN博客 vm-bhyve&#xff1a;bhyve虚拟机的管理系统FreeBSD-CSDN博客 现在&#xff0c;我…

从零开始做题:LSB

1 题目 2 解题 2.1 使用stegsolve工具 ┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc] └─$ java -jar Stegsolve.jar 2.1.1 发现R、G、B的plane0有隐藏信息 2.1.2 提取隐藏信息 2.1.3 save bin后得到二维码 2.1.4 QR Research得到flag 3 flag cumtctf{1sb_i4_s0_Ea4y}

9种慢慢被淘汰的编程语言...【送源码】

技术不断进步&#xff0c;我们使用的编程语言也不例外。 随着人工智能的兴起以及对编程语言使用的影响&#xff0c;我们更加关注哪些语言将在未来继续流行&#xff0c;哪些会被淘汰。 Python、Java 和 JavaScript 等多功能编程语言正在主导市场&#xff0c;而其他一些语言则逐…

Android实现录音并保存为wav文件

场景 在Android中怎样实现类似发送语音消息功能前的按键录音并将其显示在RecyclerView上并且能点击录音文件进行播放。 一、使用AudioRrecord录音 赋予录音权限 打开AndroidManifest.xml <uses-permission android:name="android.permission.WRITE_EXTERNAL_ST…