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" />

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL 审核在 CloudQuery 的四大场景应用

数据库作为数据的核心载体&#xff0c;其安全性和稳定性对业务的影响至关重要。而在我们日常业务中&#xff0c;SQL 编写不当是引起数据库故障的一个重要原因&#xff0c;轻则影响数据库性能&#xff0c;重则可能直接导致「雪崩」。因此&#xff0c;SQL 审核作为 SQL 代码投入生…

uniapp: 微信小程序包体积超过2M的优化方法

一、问题描述 在使用uniapp进行微信小程序开发时&#xff0c;经常会遇到包体积超过2M而无法上传&#xff1a; 二、解决方案 目前关于微信小程序分包大小有以下限制&#xff1a; 整个小程序所有分包大小不超过 30M&#xff08;服务商代开发的小程序不超过 20M&#xff09; 单个…

Node.Js+Knex+MySQL增删改查的简单示例(Typescript)

数据库: CREATE DATABASE MyDB; CREATE TABLE t_users (user_id int(11) NOT NULL,user_name varchar(10) NOT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8; 项目结构: package.json如下&#xff0c;拷贝并替换你们本地的package.json后运行 npm install 命令安装所需要的依赖。…

fastadmin多个表crud连表操作步骤

1、crud命令 php think crud -t xq_user_credential -u 1 -c credential -i voucher_type,nickname,user_id,voucher_url,status,time --forcetrue2、修改控制器controller文件 <?phpnamespace app\admin\controller;use app\common\controller\Backend;/*** 凭证信息…

【论文阅读】利用SEM二维图像表征黏土矿物三维结构

导言 在油气储层研究中&#xff0c;黏土矿物对流体流动的影响需要在微观尺度上理解&#xff0c;但传统的二维SEM图像难以完整地表征三维孔隙结构。常规的三维成像技术如FIB-SEM&#xff08;聚焦离子束扫描电子显微镜&#xff09;虽然可以获取高精度的3D图像&#xff0c;但成本…

JavaScript 中的 undefined 、null 与 NaN :概念解析与对比

文章目录 &#x1f4af;前言&#x1f4af;undefined1. 什么是 undefined2. undefined 的使用场景3. undefined 的特性 &#x1f4af;null1. 什么是 null2. null 的使用场景3. null 的特性 &#x1f4af;NaN1. 什么是 NaN2. NaN 的使用场景3. NaN 的特性 &#x1f4af;三者的区别…

C++编程技巧与规范-类和对象

类和对象 1. 静态对象的探讨与全局对象的构造顺序 静态对象的探讨 类中的静态成员变量(类类型静态成员) 类中静态变量的声明与定义&#xff08;类中声明类外定义&#xff09; #include<iostream> using namespace std;namespace _nmspl {class A{public:A():m_i(5){…

python遇到问题

1&#xff0c;BeautifulSoup lxml 解析器安装 问 1&#xff0c;BeautifulSoup lxml 解析器安装2&#xff0c;BeautifulSoup 如何引入第三方库 BeautifulSoup lxml&#xff0c;默认是导入的是python内置的解析器答1 1. 安装 Python 和 pip 确保你已经安装了 Python 和 pip。你…

async 和 await的使用

一、需求 点击按钮处理重复提交&#xff0c;想要通过disabled的方式实现。 但是点击按钮调用的方法里有ajax、跳转、弹窗等一系列逻辑操作&#xff0c;需要等方法里流程都走完&#xff0c;再把disabled设为false&#xff0c;这样下次点击按钮时就可以继续走方法里的ajax等操作…

MacOS下,如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能

MacOS下&#xff0c;如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能 在Mac上的Safari浏览器中&#xff0c;可以通过实况文本功能来实现图片中的文本翻译。关闭步骤具体步骤如下&#xff1a; 在浏览器地址栏&#xff0c;鼠标右击翻译按钮&#xff0c;然后点击“首选…

31.2 DOD压缩和相关的prometheus源码解读

本节重点介绍 : 时序数据时间的特点DOD压缩原理讲解dod压缩过程讲解dod压缩 prometheus源码解读 时序数据时间的特点 持续采集采集间隔固定&#xff0c;如prometheus配置job中的scrape_interval参数每隔15秒采集一次 - job_name: node_exporterhonor_timestamps: truescrape…

推荐一款好用的ios传输设备管理工具:AnyTrans for iOS

AnyTrans for iOS是一款好用的ios传输设备管理工具&#xff0c;可以方便用户对iphone、ipad、ipod中的文件进行管理操作&#xff0c;可以方便用户在电脑上进行各类文件的管理操作&#xff0c;支持联系人、视频、音频、短信、图片等文件的导入&#xff0c;软件支持双向传输和浏览…

快速利用c语言实现线性表(lineList)

线性表是数据结构中最基本和简单的一个&#xff0c;它是n的相同类型数据的有序序列&#xff0c;我们也可以用c语言中的数组来理解线性表。 一、线性表声明 我们定义一个线性表的结构体&#xff0c;内部有三个元素&#xff1a;其中elem是一个指针&#xff0c;指向线性表的头&am…

计算机毕业设计Python+CNN卷积神经网络股票预测系统 股票推荐系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

QT QLineEdit失去焦点事件问题与解决

本文介绍如何获得QLineEdit的失去焦点事件和获得焦点的输入框也会触发失去焦点事件的问题&#xff01; 目录 一、QLineEdit获得失去焦点事件 1.自定义类继承自QLineEdit 2.重写 focusOutEvent 3.使用 二、失去焦点事件问题 1.问题描述 2.问题解决 三、源码分享 lineed…

vscode执行npm install报错

npm install一直提示报错 以管理员身份运行vscode&#xff0c;如果每次觉得很麻烦可以做如下修改&#xff1a;

【算法】树状数组

前言 众所周知&#xff0c;通过前缀和&#xff0c;我们可以很快的在一个很大的数组中求出区间和&#xff0c;但是如果想要去修改数组中的一个数的值&#xff0c;前缀和就无法实现。所以来学习一个新的数据结构&#xff1a;树状数组 &#xff08;文章中关于树状数组的截图来自于…

Java项目实战II基于微信小程序的私家车位共享系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在城市化进…

ZeroSSL HTTPS SSL证书ACMESSL申请3个月证书

目录 一、引言 二、准备工作 三、申请 SSL 证书 四、证书选型 五、ssl重要性 一、引言 目前免费 Lets Encrypt、ZeroSSL、BuyPass、Google Public CA SSL 证书&#xff0c;一般免费3-6个月。从申请难易程度分析&#xff0c;zerossl申请相对快速和简单&#xff0c;亲测速度非…

pipx安装提示找不到包

执行&#xff1a; pipx install --include-deps --force "ansible6.*"WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by NewConnectionError(<pip._vendor.urllib3.connection.HTTPSConnection …