Gin HTML 模板渲染

1、全部模板放在一个目录里面的配置方法

1 、我们首先在项目根目录新建 templates 文件夹,然后在文件夹中新建 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1> 这是一个 html 模板 </h1>
<h3>{{.title}}</h3>
</body>
</html>

 2Gin 框架中使用 c.HTML 可以渲染模板,渲染模板前需要使用 LoadHTMLGlob()或者

LoadHTMLFiles() 方法加载模板。
package main
import (
        "net/http"
        "github.com/gin-gonic/gin"
)
func main() {
        router := gin.Default()
        router.LoadHTMLGlob("templates/*")
        //router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")
        router.GET("/", func(c *gin.Context) {
                c.HTML(http.StatusOK, "index.html", gin.H{
                        "title": "Main website",
                })
        })
        router.Run(":8080")
}

2、模板放在不同目录里面的配置方法 

Gin 框架中如果不同目录下面有同名模板的话我们需要使用下面方法加载模板
注意: 定义模板的时候需要通过 define 定义名称
templates/admin/index.html
<!-- 相当于给模板定义一个名字 define end 成对出现 -->
{{ define "admin/index.html" }}
        <!DOCTYPE html>
        <html lang="en">
        <head>
                <meta charset="UTF-8">
                <meta http-equiv="X-UA-Compatible" content="IE=edge">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>Document</title>
        </head>
        <body>
                <h1>后台模板</h1>
                <h3>{{.title}}</h3>
        </body>
        </html>
{{ end }}

 templates/default/index.html

<!-- 相当于给模板定义一个名字 define end 成对出现 -->
{{ define "default/index.html" }}
        <!DOCTYPE html>
        <html lang="en">
        <head>
                <meta charset="UTF-8">
                <meta http-equiv="X-UA-Compatible" content="IE=edge">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>Document</title>
        </head>
        <body>
                <h1>前台模板</h1>
                <h3>{{.title}}</h3>
        </body>
        </html>
{{end}}

 业务逻辑

package main
import (
        "net/http"
        "github.com/gin-gonic/gin"
)
func main() {
        router := gin.Default()
        router.LoadHTMLGlob("templates/**/*")
        router.GET("/", func(c *gin.Context) {
                c.HTML(http.StatusOK, "default/index.html", gin.H{
                        "title": "前台首页",
                })
        })
        router.GET("/admin", func(c *gin.Context) {
                c.HTML(http.StatusOK, "admin/index.html", gin.H{
                        "title": "后台首页",
                })
        })
        router.Run(":8080")
}

 注意:如果模板在多级目录里面的话需要这样配置 r.LoadHTMLGlob("templates/**/**/*") /**

表示目录

3gin 模板基本语法

1{{.}} 输出数据

模板语法都包含在 {{ }} 中间,其中 {{.}} 中的点表示当前对象。
当我们传入一个结构体对象时,我们可以根据 . 来访问结构体的对应字段。例如:
业务逻辑
package main
import (
        "net/http"
        "github.com/gin-gonic/gin"
)
type UserInfo struct {
        Name string
        Gender string
        Age int
}
func main() {
        router := gin.Default()
        router.LoadHTMLGlob("templates/**/*")
        user := UserInfo{
                Name: "张三 ",
                Gender: "男",
                Age: 18,
        }
        router.GET("/", func(c *gin.Context) {
                c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{
                        "title": "前台首页",
                        "user": user,
                })
        })
        router.Run(":8080")
}

 模板

<!-- 相当于给模板定义一个名字 define end 成对出现 -->
{{ define "default/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
</head>
<body>
        <h1>前台模板 </h1>
        <h3>{{.title}}</h3>
        <h4>{{.user.Name}}</h4>
        <h4>{{.user.Age}}</h4>
</body>
</html>
{{end}}

2.注释 

{{/* a comment */}}

 注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止。

3、变量

我们还可以在模板中声明变量,用来保存传入模板的数据或其他语句生成的结果。具体语法
如下:
<h4>{{$obj := .title}}</h4>
<h4>{{$obj}}</h4>

4.移除空格

有时候我们在使用模板语法的时候会不可避免的引入一下空格或者换行符,这样模板最终渲
染出来的内容可能就和我们想的不一样,这个时候可以使用 {{- 语法去除模板内容左侧的所有
空白符号, 使用 -}} 去除模板内容右侧的所有空白符号。
例如
{{- .Name -}}

 注意:-要紧挨{{}},同时与模板值之间需要使用空格分隔。

5.比较函数

布尔函数会将任何类型的零值视为假,其余视为真。
下面是定义为函数的二元比较运算的集合:
eq 如果 arg1 == arg2 则返回真
ne 如果 arg1 != arg2 则返回真
lt 如果 arg1 < arg2 则返回真
le 如果 arg1 <= arg2 则返回真
gt 如果 arg1 > arg2 则返回真
ge 如果 arg1 >= arg2 则返回真

6.条件判断

Go 模板语法中的条件判断有以下几种
{{if pipeline}} T1 {{end}}
{{if pipeline}} T1 {{else}} T0 {{end}}
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
{{if gt .score 60}}
及格
{{else}}
不及格
{{end}}
{{if gt .score 90}}
优秀
{{else if gt .score 60}}
及格
{{else}}
不及格
{{end}}

 7.range

Go 的模板语法中使用 range 关键字进行遍历,有以下两种写法,其中 pipeline 的值必须是数
组、切片、字典或者通道。
{{range $key,$value := .obj}}
{{$value}}
{{end}}

 如果 pipeline 的值其长度为 0,不会有任何输出

{{$key,$value := .obj}}
{{$value}}
{{else}}
pipeline 的值其长度为 0
{{end}}

 如果 pipeline 的值其长度为 0,则会执行 T0

router.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{
                "hobby": []string{"吃饭", " 睡觉 ", " 写代码 "},
        })
})
{{range $key,$value := .hobby}}
        <p>{{$value}}</p>
{{end}}

8.With 

user := UserInfo{
        Name:
        "张三 ",
        Gender: "男 ",
        Age: 18,
}
router.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{
                "user": user,
        })
})

不适应with输出数据:

<h4>{{.user.Name}}</h4>
<h4>{{.user.Gender}}</h4>
<h4>{{.user.Age}}</h4>

使用with输出数据:

{{with .user}}
        <h4>姓名: {{.Name}}</h4>
        <h4>性别: {{.user.Gender}}</h4>
        <h4>年龄: {{.Age}}</h4>
{{end}}

简单理解:相当于 var .=.user

9.预定义函数 (了解)

执行模板时,函数从两个函数字典中查找:首先是模板函数字典,然后是全局函数字典。一
般不在模板内定义函数,而是使用 Funcs 方法添加函数到模板里。

预定义的全局函数如下:

and

        函数返回它的第一个 empty 参数或者最后一个参数;
        就是说"and x y" 等价于 "if x then y else x" ;所有参数都会执行;
or
        返回第一个非 empty 参数或者最后一个参数;
        亦即"or x y" 等价于 "if x then x else y" ;所有参数都会执行;
not
        返回它的单个参数的布尔值的否定
len
        返回它的参数的整数类型长度
index
        执行结果为第一个参数以剩下的参数为索引/ 键指向的值;
        如"index x 1 2 3" 返回 x[1][2][3] 的值;每个被索引的主体必须是数组、切片或者字典。
print
        即 fmt.Sprint
printf
        即 fmt.Sprintf
println
        即 fmt.Sprintln
html
        返回与其参数的文本表示形式等效的转义 HTML
        这个函数在 html/template 中不可用。
urlquery
        以适合嵌入到网址查询中的形式返回其参数的文本表示的转义值。
        这个函数在 html/template 中不可用。
js
        返回与其参数的文本表示形式等效的转义 JavaScript
call
        执行结果是调用第一个参数的返回值,该参数必须是函数类型,其余参数作为调用该函
        数的参数;
        如"call .X.Y 1 2" 等价于 go 语言里的 dot.X.Y(1, 2)
        其中 Y 是函数类型的字段或者字典的值,或者其他类似情况;
        call 的第一个参数的执行结果必须是函数类型的值(和预定义函数如 print 明显不同);
        该函数类型值必须有 1 2 个返回值,如果有 2 个则后一个必须是 error 接口类型;
        如果有 2 个返回值的方法返回的 error nil ,模板执行会中断并返回给调用模板执行者
        该错误;
{{len .title}}
{{index .hobby 2}}

 10.自定义模板函数

router.SetFuncMap(template.FuncMap{
        "formatDate": formatAsDate,
})
package main
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.SetFuncMap(template.FuncMap{
                "formatDate": formatAsDate,
        })
        //加载模板
        router.LoadHTMLGlob("templates/**/*")
        router.GET("/", func(c *gin.Context) {
                c.HTML(http.StatusOK, "default/index.html", map[string]interface{}{
                         "title": "前台首页",
                        "now": time.Now(),
                })
        })
        router.Run(":8080")
}

模板里面的用法

{{.now | formatDate}}
或者
{{formatDate .now }}

 4.嵌套 template

1 、新建 templates/deafult/page_header.html
{{ define "default/page_header.html" }}
        <h1>这是一个头部 </h1>
{{end}}

 2、外部引入

注意:
1 、引入的名字为 page_header.html 中定义的名字
2 、引入的时候注意最后的点( .
{{template "default/page_header.html" .}}

<!-- 相当于给模板定义一个名字 define end 成对出现 -->
{{ define "default/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
</head>
<body>
        {{template "default/page_header.html" .}}
</body>
</html>
{{end}}

5.静态文件服务

当我们渲染的 HTML 文件中引用了静态文件时 , 我们需要配置静态 web 服务
r.Static("/static", "./static")
前面的 /static 表示路由
后面的 ./static 表示路径
func main() {
        r := gin.Default()
        r.Static("/static", "./static")
        r.LoadHTMLGlob("templates/**/*")
        // ...
        r.Run(":8080")
}
<link rel="stylesheet" href="/static/css/base.css" />

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

数字化转型企业架构设计手册(交付版),企业数字化转型建设思路、本质、数字化架构、数字化规划蓝图(PPT原件获取)

1、企业架构现状分析 2、企业架构内容框架 3、企业架构设计方法 3.1 、业务架构设计方法 3.2 、数据架构设计方法 3.3 、应用架构设计方法 3.4 、技术架构设计方法 软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&…

⾃动化运维利器Ansible-基础

Ansible基础 一、工作原理二、快速入门2.1 测试所有资产的网络连通性2.2 发布文件到被管理节点(资产) 三、资产(被管理节点)3.1 静态资产3.1.1 自定义资产3.1.2 自定义资产的使用3.1.3 资产选择器 四、Ansible Ad-Hoc 命令4.1 模块类型4.1.1 command & shell 模块4.1.2 cop…

鸿蒙NEXT自定义组件:太极Loading

【引言】&#xff08;完整代码在最后面&#xff09; 本文将介绍如何在鸿蒙NEXT中创建一个自定义的“太极Loading”组件&#xff0c;为你的应用增添独特的视觉效果。 【环境准备】 电脑系统&#xff1a;windows 10 开发工具&#xff1a;DevEco Studio NEXT Beta1 Build Vers…

AVL树了解并简单实现

这篇文章默认知道二叉搜索树&#xff0c;如果了解并不多可以先看看二叉搜索树了解和实现-CSDN博客 目录 1.AVL树概念 2.AVL树节点定义 3.AVL树的插入&#xff08;重点&#xff09; 3.1AVL树 3.2AVL树的旋转 3.3AVL树插入代码 4.AVL树的验证 5.AVL树的删除 6.AVL树的性能…

【MySQL】索引原理及操作

目录 索引原理 初识索引 磁盘原理 磁盘与系统之间的关系 MySQL、系统、磁盘之间的关系 理解索引 页目录 页目录设计的数据结构问题 聚簇索引与非聚簇索引 遗留问题 索引操作 创建索引 查询索引 删除索引 其他索引概念与操作 索引原理 索引&#xff08;I…

代码随想录算法训练营第三十一天| 56. 合并区间 、738.单调递增的数字 。c++转java

56. 合并区间 class Solution {public int[][] merge(int[][] intervals) {//对区间按照右边界排序Arrays.sort(intervals,(a,b) -> Integer.compare(a[0],b[0]));List<int[]> p new LinkedList<>();int l intervals[0][0],r intervals[0][1];for(int i 1;i…

厦大南洋理工最新开源,一种面向户外场景的特征-几何一致性无监督点云配准方法

导读 本文提出了INTEGER&#xff0c;一种面向户外点云数据的无监督配准方法&#xff0c;通过整合高层上下文和低层几何特征信息来生成更可靠的伪标签。该方法基于教师-学生框架&#xff0c;创新性地引入特征-几何一致性挖掘&#xff08;FGCM&#xff09;模块以提高伪标签的准确…

模型运行速度笔记: s/epoch VS s/iter

1 概念介绍 在模型训练中&#xff1a; s/epoch 表示每个epoch所需的秒数&#xff0c;即完成一轮完整数据集训练的时间。s/iter 表示每个iteration&#xff08;迭代&#xff09;所需的秒数&#xff0c;即处理一个batch的时间。 它们的关系是&#xff1a; 2 举例 比如我tra…

k8s 中传递参数给docker容器

文章目录 docker启动时传递参数使用k8s env传递完全覆盖 ENTRYPOINT 和 CMD 在 Kubernetes 中&#xff0c;可以通过多种方式将参数传递给 Dockerfile 或其运行的容器&#xff0c;常见的方式包括使用环境变量、命令行参数、配置文件等。以下是一些常用的方法&#xff1a; docker…

Map Set

在学习TreeMap和TreeSet之前需要先学习有关搜索树的相关知识以及接口Map和Set。 1. 搜索树 1.1 概念 二叉搜索树又称二叉排序树&#xff0c;其特点是&#xff0c;该节点的左边都比其小&#xff0c;右边都比其大&#xff0c;每一棵子树都必须满足这个条件。如下图所示例子。2…

Android OpenGLES2.0开发(八):Camera预览

严以律己&#xff0c;宽以待人 引言 终于到该章节了&#xff0c;还记得Android OpenGLES2.0开发&#xff08;一&#xff09;&#xff1a;艰难的开始章节说的吗&#xff1f;写这个系列的初衷就是因为每次用到GLSurfaceViewCamera预览时&#xff0c;总是CtrlC、CtrlV从来没有研究…

基础 IO

目录 一、基本共识 二、复习C语言中的文件操作 三、与文件操作有关的系统调用接口 1. open 与 close 1.1 umask 2. write 3. read 四、如何理解文件 1. 文件描述符 fd 2. 文件fd分配规则 3. 重定向的引入 4. 重定向的本质 5. dup2 6. 理解 >、>>、…

ThriveX 博客管理系统前后端项目部署教程

前端 前端项目地址&#xff1a;https://github.com/LiuYuYang01/ThriveX-Blog 控制端项目地址&#xff1a;https://github.com/LiuYuYang01/ThriveX-Admin Vercel 首先以 Vercel 进行部署&#xff0c;两种方式部署都是一样的&#xff0c;我们以前端项目进行演示 首先我们先…

[含文档+PPT+源码等]精品基于springboot实现的原生Andriod手机使用管理软件

软件开发环境及开发工具&#xff1a; 数据库管理工具&#xff1a;phpstudy/Navicat或者phpstudy/sqlyog 开发工具&#xff1a;Android Studio 后台管理系统涉及技术&#xff1a; 后台使用框架&#xff1a;Springboot 前端使用技术&#xff1a;Vue,HTML5,CSS3、JavaScript等…

华为三层交换机禁止VLAN间通讯(两种解决方案)

在日常办公中&#xff0c;有时会禁止内网中各个部门间的访问&#xff0c;例如&#xff1a; ①访客不能访问内网任何终端及服务器 ②财务部门不能被其他部门访问 实验环境&#xff1a;华为Ensp模拟器 内网架构&#xff1a;三层网络 环境说明&#xff1a;三层交换机承载着网…

为以人工智能为中心的工作负载重新设计的全局控制台

MinIO 控制台多年来一直是一个不断发展的产品。每次学习时&#xff0c;我们都会思考如何改进交互框架中这个非常重要的部分。首先是控制台&#xff0c;它在推出后的一年内就被广泛采用。更具体地说&#xff0c;超过 10K 个组织。接下来是企业控制台。这从对象存储与其 GUI 之间…

stm32在linux环境下的开发与调试

环境安装 注&#xff1a;文末提供一键脚本 下载安装stm32cubeclt 下载地址为&#xff1a;https://www.st.com/en/development-tools/stm32cubeclt.html 选择 linux版本下载安装 安装好后默认在家目录st下 > $ ls ~/st/stm32cubeclt_1.16.0 …

【leetcode】N皇后 回溯法c++

目录 51.N皇后 52.N皇后II 51.N皇后 51. N 皇后 - 力扣&#xff08;LeetCode&#xff09; 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间…

GESP4级考试语法知识(贪心算法(六))

寻找平面上的极大点代码 #include<iostream> #include<algorithm> using namespace std; struct node {int x,y; }a[101]; bool vis[101]; bool cmp(node A,node B) {if(A.x!B.x) return A.x<B.x;return A.y<B.y; } int main() {int n;cin>>n;for(int…

如何构建高效的知识库系统?实现智能信息管理

在当今信息化迅速发展的时代&#xff0c;企业和组织面临着海量信息的挑战。如何有效地管理这些信息&#xff0c;使其安全、易于访问&#xff0c;并且能够快速响应用户的需求&#xff0c;成为了智慧管理的核心。而知识库系统(Knowledge Base System)正是为了解决这一问题而应运而…