内容展示

更多Go内容请见: https://blog.csdn.net/weixin_39777626/article/details/85066750

模板引擎

类型

  • 无逻辑模板引擎:将模板中指定的占位符替换成相应的动态数据
  • 嵌入逻辑模板引擎:执行代码,并进行相应的字符串替换工作

Go 模板引擎

语法分析——ParseFile()
执行模板——Execute()

工作原理
在这里插入图片描述
一个简单的模板

<! DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Go Web Programming</title>
	</head>
	<body>
		{{.}}
	</body>
</html>

在处理器函数中出发模板引擎

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("tmpl.html")
	t.Execute(w, "Hello World!")
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

动作

条件动作

在这里插入图片描述
在处理器中生成随机数

package main

import (
	"html/template"
	"math/rand"
	"net/http"
	"time"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("tmpl.html")
	rand.Seed(time.Now().Unix())
	t.Execute(w, rand.Intn(10) > 5)
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

tmpl.html 文件(使用了条件语句)

<! DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Go Web Programming</title>
	</head>
	<body>
		{{if .}}
			Number is greater than 5 !
		{{else}}
			Number is 5 or less !
		{{end}}
	</body>
</html>
迭代动作

在这里插入图片描述
调用迭代动作

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("tmpl.html")
	days := []string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}
	t.Execute(w, days)
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

tmpl.html 文件(使用了迭代语句)

<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Go Web Programming</title>
	</head>
	<body>
		<ul>
		{{range . }}
			<li>{{ . }}</li>
		{{end}}
		</ul>
	</body>
</html>

tmpl.html 文件(带有备选结果的迭代语句)

<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Go Web Programming</title>
	</head>
	<body>
		<ul>
		{{range . }}
			<li>{{ . }}</li>
		{{else}}
			<li>Nothing to show</li>
		{{end}}
		</ul>
	</body>
</html>
设置动作

在这里插入图片描述

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("tmpl.html")
	t.Execute(w, "hello")
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

tmpl.html 文件(对点进行设置)

<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Go Web Programming</title>
	</head>
	<body>
		<div>The dot is {{ . }}</div>
		<div>
			{{with "world"}}
				Now the dot is set to {{ . }}
			{{end}}
		</div>
		<div>The dot is {{ . }} again</div>
	</body>
</html>

tmpl.html 文件(在设置点的时候提供备选方案)

<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Go Web Programming</title>
	</head>
	<body>
		<div>The dot is {{ . }}</div>
		<div>
			{{with "world"}}
				Now the dot is set to {{ . }}
			{{else}}
				The dot is still {{ . }}
			{{end}}
		</div>
		<div>The dot is {{ . }} again</div>
	</body>
</html>
包含动作

t1.html

<html lang="en">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=9">
		<title>Go Web Programming</title>
	</head>
	<body>
		<div>This is t1.html before</div>
		<div>This is the value of the dot in t1.html - [{{ . }}]</div>
		<hr/>
		{{template "t2.html"}}
		<hr/>
		<div>This is t1.html after</div>
	</body>
</html>

t2.html

<div style="background-color : yellow ;">
	This is t2.html<br/>
	This is the value of the dot in t2.html - [{{ . }}]
</div>

调用嵌套模块

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("t1.html", "t2.html")
	t.Execute(w, "hello world")
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

t1.html (将 t1.html 中的数据传递给 t2.html )

<html lang="en">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=9">
		<title>Go Web Programming</title>
	</head>
	<body>
		<div>This is t1.html before</div>
		<div>This is the value of the dot in t1.html - [{{ . }}]</div>
		<hr/>
		{{template "t2.html" . }}
		<hr/>
		<div>This is t1.html after</div>
	</body>
</html>

参数、变量和管道

在这里插入图片描述

函数

模板引擎函数 输入 多个参数
返回一个值
一个值和一个错误

创建自定义模板函数
在这里插入图片描述

package main

import (
	"html/template"
	"net/http"
	"time"
)

func formatDate(t time.Time) string {
	layout := "2006-01-02"
	return t.Format(layout)
}

func process(w http.ResponseWriter, r *http.Request) {
	funcMap := template.FuncMap{"fdate": formatDate}
	t := template.New("tmpl.html").Funcs(funcMap)
	t, _ = t.ParseFiles("tmpl.html")
	t.Execute(w, time.Now())
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

tmpl.html(通过管道使用自定义函数)

<html>

	<head>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

		<title>Go Web Programming</title>

	</head>

	<body>

		<div>The date/time is {{ . | fdate }}</div>

	</body>

</html>

tmpl.html(通过传递参数使用自定义函数)

<html>

	<head>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

		<title>Go Web Programming</title>

	</head>

	<body>

		<div>The date/time is {{ fdate . }}</div>

	</body>

</html>

上下文感知

定义: 可以根据内容所处的上下文改变其显示的内容
用途:

  • 对被显示的内容实施正确的转义
  • 实现自动的防御编程

展示模板上下文感知

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("tmpl.html")
	content := `I asked:<i>"What's up?"</i>`
	t.Execute(w, content)
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

tmpl.html(上下文感知模板)

<html>

	<head>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

		<title>Go Web Programming</title>

	</head>

	<body>

		<div>{{ . }}</div>

		<div><a href="/{{ . }}">Path</a></div>

		<div><a href="/?q={{ . }}">Query</a></div>

		<div><a onclick="f('{{ . }}')">Onclick</a></div>

	</body>

</html>
防御XSS攻击

持久性XSS漏洞(XSS攻击方式):服务器将攻击者存储的数据原原本本地显示给其他用户

form.html(实施XSS攻击的表单)

<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Go Web Programming</title>
	</head>
	<body>
		<form action="/process" method="post">
			Comment:<input name="comment" type="text">
			<hr/>
			<button id="submit">Submit</button>
		</form>
	</body>
</html>

测试XSS攻击

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("tmpl.html")
	t.Execute(w, r.FormValue("comment"))
}

func form(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("form.html")
	t.Execute(w, nil)
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	http.HandleFunc("/form", form)
	server.ListenAndServe()
}

tmpl.html

<html>

	<head>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

		<title>Go Web Programming</title>

	</head>

	<body>

		<div>{{ . }}</div>

	</body>

</html>
<script>alert('Pwnd!');</script>
不对HTML进行转义

FireFox

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("tmpl.html")
	t.Execute(w, template.HTML(r.FormValue("comment")))
}

func form(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("form.html")
	t.Execute(w, nil)
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	http.HandleFunc("/form", form)
	server.ListenAndServe()
}

关闭内置XSS防御功能(IE,Chrome,Safari)

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("X-XSS-Protection", "0")
	t, _ := template.ParseFiles("tmpl.html")
	t.Execute(w, template.HTML(r.FormValue("comment")))
}

func form(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("form.html")
	t.Execute(w, nil)
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	http.HandleFunc("/form", form)
	server.ListenAndServe()
}

嵌套模板

布局:可以重复在多个页面上的固定模式

显示地定义一个模板

{{ define "layout" }}
<html>

	<head>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

		<title>Go Web Programming</title>

	</head>

	<body>

		{{ template "content" }}

	</body>

</html>
{{ end }}

layout.html(在一个模板文件中定义多个模板)

{{ define "layout" }}
<html>

	<head>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

		<title>Go Web Programming</title>

	</head>

	<body>

		{{ template "content" }}
	</body>

</html>
{{ end }}

{{ define "content" }}
	Hello World !
{{ end }}

使用显式定义的模板

package main

import (
	"html/template"
	"net/http"
)

func process(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("layout.html")
	t.ExecuteTemplate(w, "layout", "")
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

red_hello.html

{{ define "content" }}
<h1 style="color:red;">Hello World!</h1>
{{ end }}

blue_hello.html

{{ define "content" }}
<h1 style="color:blue;">Hello World!</h1>
{{ end }}

不同模板中定义的同名模板

package main

import (
	"html/template"
	"math/rand"
	"net/http"
	"time"
)

func process(w http.ResponseWriter, r *http.Request) {
	rand.Seed(time.Now().Unix())
	var t *template.Template
	if rand.Intn(10) > 5 {
		t, _ = template.ParseFiles("layout.html", "red_hello.html")
	} else {
		t, _ = template.ParseFiles("layout.html", "blue_hello.html")
	}
	t.ExecuteTemplate(w, "layout", "")
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

通过块动作定义默认模板

块动作:允许用户定义一个模板并且立即使用
在这里插入图片描述
只对layout.html进行语法分析

package main

import (
	"html/template"
	"math/rand"
	"net/http"
	"time"
)

func process(w http.ResponseWriter, r *http.Request) {
	rand.Seed(time.Now().Unix())
	var t *template.Template
	if rand.Intn(10) > 5 {
		t, _ = template.ParseFiles("layout.html", "red_hello.html")
	} else {
		t, _ = template.ParseFiles("layout.html")
	}
	t.ExecuteTemplate(w, "layout", "")
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/process", process)
	server.ListenAndServe()
}

layout.html(通过块动作添加默认的content模板)

{{ define "layout" }}
<html>

	<head>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

		<title>Go Web Programming</title>

	</head>

	<body>

		{{ block "content" . }}
		<h1 style="color:blue;">Hello World!</h1>
		{{ end }}
	</body>

</html>

更多Go内容请见: https://blog.csdn.net/weixin_39777626/article/details/85066750

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值