Go语言的template
html/template包实现了数据驱动的模板,用于生成可防止代码注入的安全的HTML内容。它提供了和 text/template包相同的接口,Go语言中输出HTML的场景都应使用html/template这个包。
html/template会自动帮你转义掉有风险的代码,避免xss攻击
模板需要注意的
- 模板文件通常定义为.tmpl和.tpl为后缀(也可以使用其他的后缀),必须使用UTF8编码。
- 模板文件中使用{{和}}包裹和标识需要传入的数据。
- 传给模板这样的数据就可以通过点号(.)来访问,如果数据是复杂类型的数据,可以通过{ { .FieldName }}来访问它的字段。
- 除{{和}}包裹的内容外,其他内容均不做修改原样输出。
- 模板三步
- 定义模板
- 解析模板
- 渲染模板
模板文件
{{/*定义模板*/}}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>hello</title>
</head>
<body>
<p>hello {{ . }}</p>
</body>
</html>
go服务端
package main
import (
"net/http"
"text/template"
)
func hello(w http.ResponseWriter, r *http.Request) {
//打开模板
t, err := template.ParseFiles("template/hello.tmpl")
if err != nil {
return
}
//渲染模板
name := "hello"
err := t.Execute(w, name)
if err != nil {
return
}
}
func main() {
http.HandleFunc("/", hello)
err := http.ListenAndServe(":9090", nil)
if err != nil {
return
}
}
map作为参数传入,直接使用参数访问
服务端
m1 := map[string]interface{}{
"name": "ll",
"gender": "female",
"age": 0,
}
模板文件
<p>hello {{ .name }}</p>
<p>hello {{ .age }}</p>
<p>hello {{ .gender }}</p>
结构体传入
名称必须是要大写才能被外界访问到
type User struct {
Name string
Gender string
Age int
}
u1 := User{
Name: "ll",
Gender: "female",
Age: 0,
}
模板文件
<p>hello {{ .Name }}</p>
<p>hello {{ .Age }}</p>
<p>hello {{ .Gender }}</p>
想要一次传入多个参数,可以使用map来进行传入
u1 := User{
Name: "struct_para",
Gender: "female",
Age: 0,
}
m1 := map[string]interface{}{
"name": "map_para",
"gender": "female",
"age": 0,
}
err = t.Execute(w, map[string]interface{}{
"struct": u1,
"map_itf": m1,
})
模板文件
<p>hello {{ .struct.Name }}</p>
<p>hello {{ .map_itf.name }}</p>
变量
{{$v := 114}}
{{$}}
移除空格
移除左右的空格
{{- .name -}}
条件判断
{{ $v1 := 114 }}
{{if $v1}}
{{$v1}}
{{else}}
Nothing
{{end}}
预定义函数
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,模板执行会中断并返回给调用模板执行者该错误;
比较函数
eq 如果arg1 == arg2则返回真
ne 如果arg1 != arg2则返回真
lt 如果arg1 < arg2则返回真
le 如果arg1 <= arg2则返回真
gt 如果arg1 > arg2则返回真
ge 如果arg1 >= arg2则返回真
循环
{{range $idx,$hobby := .hobby}}
<p>{{$idx}} - {{$hobby}}</p>
{{else}}
empty
{{end}}
with共同前缀
类似 var . = .struct
{{with .struct}}
<p>hello {{ .Name }}</p>
<p>hello {{ .Age }}</p>
<p>hello {{ .Gender }}</p>
{{end}}
自定义函数
len := func(str string) (int, error) {
return len(str), nil
}
//渲染模板
//name := "hello"
t.Funcs(template.FuncMap{"len": len})
自定义函数用法
<p>hello {{ len .struct.Name }}</p>
模板嵌套
主模板
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>hello</title>
</head>
<body>
{{template "a.tmpl"}}
{{template "b.tmpl"}}
</body>
</html>
{{/*内部嵌套*/}}
{{define "a.tmpl"}}
<a>
<li>test_a_tmpl</li>
</a>
{{end}}
外部嵌套
b.tmpl
<b>
<li>test_b_tmpl</li>
</b>
服务端
package main
import (
"html/template"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
//先导入主文件 然后再导入嵌套文件
t, err := template.ParseFiles("template/hello.tmpl", "template/b.tmpl")
if err != nil {
return
}
t.Execute(w, nil)
}
func main() {
http.HandleFunc("/", hello)
err := http.ListenAndServe(":9090", nil)
if err != nil {
return
}
}
block模板继承
利用根模板进行组合
根模板
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{ . }}</title>
<style>
*{
margin: 0;
}
.nav{
height: 50px;
width: 100%;
position: fixed;
top: 0;
background-color: yellow;
}
.main{
margin-top: 50px;
}
.context{
width: 20%;
height: 100%;
position: fixed;
left: 0;
background-color: blue;
}
.center {
text-align: center;
}
</style>
</head>
<body>
<div class="nav"></div>
<div class="main">
<div class="menu"></div>
<div class="context center">
{{block "content" .}}{{end}}
</div>
</div>
</body>
</html>
继承模板
{{template "base.tmpl"}}
{{/*此处定义的模板要和上面的相同*/}}
{{define "content"}}
<h1>home_page</h1>
{{end}}
服务端
先根模板后继承模板
func home2(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("template/base.tmpl", "template/test_home.tmpl")
if err != nil {
return
}
t.Execute(w, "home")
}
自定义标识符
防止和其他语言发生冲突
在解析模板的时候来定义
func test(w http.ResponseWriter, r *http.Request) {
t,err := template.New("test.tmpl").
Delims("{[", "]}").
ParseFiles("template/test.tmpl")
if err != nil{
return
}
t.Execute(w,nil)
}
这样标识符就成了 {[ name ]}了
使用gin框架的template模板
package main
import (
"github.com/gin-gonic/gin"
"html/template"
"net/http"
)
func main() {
r := gin.Default()
//静态文件 解析前添加路径
r.Static("/name", "statics")
//自定义函数 解析前添加
r.SetFuncMap(template.FuncMap{
"safe": func(str string) template.HTML {
return template.HTML(str)
},
})
//模板解析 ** -> 所有文件夹 * -> 所有文件
r.LoadHTMLGlob("templates/**/*")
//访问index的时候就执行后面的函数
r.GET("/users/index", func(ctx *gin.Context) {
//http请求
ctx.HTML(http.StatusOK, "users/index.tmpl", gin.H{ //模板渲染
"title": "moreac.top",
})
})
r.GET("/posts/index", func(ctx *gin.Context) {
//http请求
ctx.HTML(http.StatusOK, "posts/index.tmpl", gin.H{ //模板渲染
"title": "moreac.top",
})
})
err := r.Run(":9090")
if err != nil {
return
}
}
{{define "posts/index.tmpl"}}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>posts/index</title>
</head>
<body>
{{ .title }}
</body>
</html>
{{end}}
静态文件处理
网页上面使用到的样式文件 .css .js pic等
Go语言的template的更多相关文章
- djiango的模板语言(template)
老师的博客:http://www.cnblogs.com/liwenzhou/p/7931828.html 官方文档:https://docs.djangoproject.com/en/1.11/re ...
- django模板语言之Template
当前端的一些数据需要后端传送过来并展示时,用到了django的模板语言,模板语言的作用就是,在后端把一些处理好的数据,通过模板语言所规定的格式,通过render渲染,放到前端页面固定的位置展示.这之间 ...
- Django模板语言(Template)
1.变量 变量相关用 { { } } 逻辑相关用{% %} 2.Filter过滤器 (1)default 如果一个变量是false或者为空,使用给定的默认值. 否则,使用变量的值. {{ va ...
- 【转】Velocity模板(VM)语言介绍
http://www.blogjava.net/caizh2009/archive/2010/08/20/329495.html Velocity是什么? Velocity是一个基于java的模板引擎 ...
- 【转载】Velocity模板引擎的介绍和基本的模板语言语法使用
原文地址http://www.itzhai.com/the-introduction-of-the-velocity-template-engine-template-language-syntax- ...
- <Django> MVT三大块之Template(模板)
1.模板简介 创建项目,基本配置 第一步:配置数据库 第二步:创建APP,配置APP 第三步:配置模板路径 第四步:配置分发urls.py(APP里面的) 根目录下,增加命名空间namespace,作 ...
- Vue + Webpack + Vue-loader 系列教程(1)功能介绍篇
原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ Vue-loader 是什么? vue-loader 是一个加载器,能把如下格式的 Vue ...
- 只需2分钟,简单构建velocity web项目
Velocity是一个基于java的模板引擎(template engine).它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象 velocity ...
- NVelocity介绍,NVelocity中文手册文档及实例下载
NVelocity是什么velocity英音:[vi'lɔsiti]美音:[və'lɑsətɪ]近在做一个项目,客户要求有网站模板功能,能够自主编辑网站的风格,因为这个系统是为政府部门做子站系统,举个 ...
- Velocity 语法(转)
一.基本语法 1."#"用来标识Velocity的脚本语句,包括#set.#if .#else.#end.#foreach.#end.#iinclude.#parse.#macro ...
随机推荐
- python tcp select 多路复用
1 #!/usr/bin/python 2 # -*- coding: UTF-8 -*- 3 # 文件名:tcpserver.py 4 5 import socket 6 import time 7 ...
- ysoserial CommonsCollections2 分析
在最后一步的实现上,cc2和cc3一样,最终都是通过TemplatesImpl恶意字节码文件动态加载方式实现反序列化. 已知的TemplatesImpl->newTransformer()是最终 ...
- 将自己的组件打包发布到npm
在项目中有些组件在各个项目中都会调用,那么将组件发布到npm ,用到的项目去下载,这样会省去一些不必要的麻烦. 将组件发布到npm 中的步骤 做个记录 1.项目的创建,我这里使用 vue init w ...
- 词向量word2vec(图学习参考资料)
介绍词向量word2evc概念,及CBOW和Skip-gram的算法实现. 项目链接: https://aistudio.baidu.com/aistudio/projectdetail/500940 ...
- 关于C++ find
#include <bits/stdc++.h> using namespace std; int a[1005]; int main() { for(int i = 0;i < 1 ...
- 第2-3-7章 个人网盘服务接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss
目录 5.8 导入其他接口代码 5.8.1 接口导入-分页查询附件 5.8.2 接口导入-根据业务类型/业务id查询附件 5.9 导入网盘服务接口 5.9.1 导入FileController 5.9 ...
- python编程学习方法及计算机基础理论
**从零开始学习编程 ** 一.学习前语 在学习python之前首先先说几点学习建议,首先是培养自己能解决问题的能力: 1.遇到问题时给自己设置一个解决该问题的时间限制 0-5min:自己解决问题(百 ...
- MySQL数据库下载以及启动软件的详细步骤
第一步>>>在浏览器上百度上搜索MySQL 如何判断官网?有官网两个字的或者纯英文解释的大概率就是官网 第二步>>>点击DOWNLOAWDS 第三步>> ...
- PGL图学习之基于GNN模型新冠疫苗任务[系列九]
PGL图学习之基于GNN模型新冠疫苗任务[系列九] 项目链接:https://aistudio.baidu.com/aistudio/projectdetail/5123296?contributio ...
- Nginx rewrite 详解
Nginx rewrite 详解 本篇主要介绍 nginx 的 rewrite 重定向这个功能进行 详解介绍, 以及介绍它的使用场景 1. rewrite 基本介绍 rewrite是实现URL重写的关 ...