当前位置:网站首页>Standard library template learning introduction original
Standard library template learning introduction original
2022-06-12 18:53:00 【Erya preaches Buddhism】
html/template
The package implements a data-driven template , Used to generate secure code that prevents code injection HTML Content . It provides and text/template
Package the same interface ,Go Output in language HTML All scenarios should use html/template
This package .
1, Template and rendering
In some cases, the front and rear ends are not separated Web Architecture , We usually need to render some data to HTML In the document , So as to realize dynamic web pages ( The layout and style of the web page are roughly the same , But the content of the display is different ) effect .
The template we are talking about here can be understood as pre-defined HTML Document file , The mechanism of template rendering can be simply understood as text replacement operation – Use the corresponding data to replace HTML Pre prepared marks in the document .
Many programming languages Web Various template engines are used in the framework , such as Python In language Flask Used in the framework jinja2 template engine .
1,Go Language template engine
Go The language has a built-in text template engine text/template
And for HTML Document html/template
. Their mechanism of action can be summarized as follows :
- Template files are usually defined as
.tmpl
and.tpl
For the suffix ( Other suffixes can also be used ), You have to useUTF8
code . - Use in template file
{{
and}}
Packages and identification need incoming data . - Such data can be passed to the template through the point number (
.
) To visit , If the data is complex type data , Can pass { { .FieldName }} To access its fields . - except
{{
and}}
Outside the contents of the package , Other contents will not be modified and output as is .
2, Use of template engine
Go The use of language template engine can be divided into three parts : Define template file 、 Parsing template files and template rendering .
1, Define template file
among , When defining the template file, we need to write it according to the relevant syntax rules , I'll give you a detailed introduction later .
2, Parse template file
After the template file is defined above , You can use the following common methods to parse the template file , Get the template object :
func (t *Template) Parse(src string) (*Template, error)
func ParseFiles(filenames ...string) (*Template, error)
func ParseGlob(pattern string) (*Template, error)
Of course , You can also use func New(name string) *Template
Function to create a file named name
The template of , Then call the above method to parse the template string or template file .
3, Template rendering
The rendering template is simply to fill the template with data , Of course, it may actually be a lot more complicated .
func (t *Template) Execute(wr io.Writer, data interface{}) error
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error
4, Basic example
1, Define template file
We are in accordance with the Go Template syntax defines a hello.tmpl
Template file , The contents are as follows :
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello</title>
</head>
<body>
<p>Hello {{.}}</p>
</body>
</html>
2, Parsing and rendering template files
And then we create one main.go
file , Write down HTTP server The end code is as follows :
// main.go
func sayHello(w http.ResponseWriter, r *http.Request) {
// Parse the specified file to generate the template object
tmpl, err := template.ParseFiles("./hello.tmpl")
if err != nil {
fmt.Println("create template failed, err:", err)
return
}
// Render templates with given data , And write the result to w
tmpl.Execute(w, " Shahe little prince ")
}
func main() {
http.HandleFunc("/", sayHello)
err := http.ListenAndServe(":9090", nil)
if err != nil {
fmt.Println("HTTP server failed,err:", err)
return
}
}
The above main.go
File compilation execution , Then use a browser to access http://127.0.0.1:9090
You can see on the page “Hello Shahe little prince ”. This is an example of the simplest template rendering ,Go For detailed usage of the language template engine, please read on .
2, Template syntax
1,{{.}}
Template syntax is contained in {{
and }}
middle , among {{.}}
The points in represent the current object .
When we pass in a struct object , We can use .
To access the corresponding fields of the structure . for example :
// main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
type User struct {
Name string
Gender string
Age int
}
func sayHello(w http.ResponseWriter, r *http.Request) {
// Define templates
// Analytical template
t, err := template.ParseFiles("./hello.tmpl")
if err != nil {
fmt.Println("parse file failed, err", err)
return
}
// Apply colours to a drawing template
//u1 := User{
// Name: "eryajf",
// Gender: " male ",
// Age: 10,
//}
// Words passed through the structure , Field names must be capitalized to access
// And by map In the form of , You do not need to capitalize , Because it is directly through key Access to the
m1 := map[string]interface{}{
"Name": " Xiao Ming ",
"Gender": " male ",
"Age": 20,
}
t.Execute(w, m1) // The structure is passed here , perhaps map It's all right
}
func main() {
http.HandleFunc("/", sayHello)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Println("Http server start failed, err", err)
return
}
}
Template file hello.tmpl
The contents are as follows :
<html lang="zh=CN">
<head>
<title>Hello</title>
</head>
<body>
<p> full name : {{ .Name }} </p>
<p> Gender : {{ .Gender }} </p>
<p> Age : {{ .Age }} </p>
</body>
</html>
Empathy , When the variable we pass in is map when , You can also use .
according to key To take a value .
2, notes
{{/* a comment */}}
notes , The execution ignores . You can do more . Comments cannot be nested , And it has to be close to the boundary .
3,pipeline
pipeline
It refers to the operation of generating data . such as {{.}}
、{{.Name}}
etc. .Go The use of pipeline symbols is supported in the template syntax of |
Link multiple commands , Usage and unix The pipe under the pipe is similar :|
The previous command changes the result of the operation ( Or return value ) The last position passed to the next command .
** Be careful :** It's not just the use of |
It's just pipeline.Go In the template syntax of ,pipeline Of
The concept is to transfer data , As long as you can generate data , All are pipeline
.
4, Variable
We can also declare variables in the template , Used to save the data passed into the template or the results generated by other statements . The specific syntax is as follows :
$obj := {{.}}
among $obj
It's the name of the variable , You can use this variable in subsequent code .
5, Remove spaces
Sometimes when we use template syntax, we will inevitably introduce spaces or line breaks , In this way, the final rendered content of the template may be different from what we think , It can be used at this time {{-
Syntax removes all blank symbols to the left of the template content , Use -}}
Remove all blank symbols to the right of the template content .
for example :
{{- .Name -}}
Be careful :-
Be close to {{
and }}
, At the same time, it needs to be separated from the template value with a space .
6, conditional
Go There are several kinds of conditional judgments in template syntax :
{{if pipeline}} T1 {{end}}
{{if pipeline}} T1 {{else}} T0 {{end}}
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
7,range
Go In the template syntax of range
Keyword traversal , There are two ways of writing , among pipeline
The value of must be an array 、 section 、 Dictionary or channel .
{{range pipeline}} T1 {{end}}
If pipeline Its length is 0, There won't be any output
{{range pipeline}} T1 {{else}} T0 {{end}}
If pipeline Its length is 0, Will perform T0.
8,with
{{with pipeline}} T1 {{end}}
If pipeline by empty No output , Otherwise it would be dot Set to pipeline And execute T1. Don't modify the outside dot.
{{with pipeline}} T1 {{else}} T0 {{end}}
If pipeline by empty, Don't change dot And implement T0, otherwise dot Set to pipeline And execute T1.
9, Predefined functions
When executing the template , Function looks up... From two function dictionaries : The first is the template function dictionary , Then there's the global function dictionary . Generally, functions are not defined in templates , But use Funcs Method to add a function to the template .
The predefined global functions are as follows :
and
Function returns its first empty Parameter or the last parameter ;
That is to say "and x y" Equivalent to "if x then y else x"; All parameters are executed ;
or
Return the first non empty Parameter or the last parameter ;
or "or x y" Equivalent to "if x then x else y"; All parameters are executed ;
not
Returns the negation of the Boolean value of its single argument
len
Returns the integer type length of its argument
index
The execution result is the first parameter, and the remaining parameters are the index / The value that the key points to ;
Such as "index x 1 2 3" return x[1][2][3] Value ; Each indexed body must be an array 、 Slice or dictionary .
print
namely fmt.Sprint
printf
namely fmt.Sprintf
println
namely fmt.Sprintln
html
Returns an escape equivalent to the text representation of its argument HTML.
This function is in the html/template Unavailable in .
urlquery
Return the escape value of the text representation of its parameters in a form suitable for embedding in the URL query .
This function is in the html/template Unavailable in .
js
Returns an escape equivalent to the text representation of its argument JavaScript.
call
The result of execution is the return value of the first parameter , The argument must be of function type , The remaining parameters are used as the parameters to call the function ;
Such as "call .X.Y 1 2" Equivalent to go In the language dot.X.Y(1, 2);
among Y Is the value of a function type field or dictionary , Or something like that ;
call The execution result of the first parameter of must be the value of the function type ( And predefined functions like print Obviously different );
The function type value must have 1 To 2 Return values , If there is 2 The latter must be error Interface type ;
If there is 2 Methods that return values return error Not nil, Template execution is interrupted and returned to the calling template executor ;
10, Comparison function
Boolean functions treat any type of zero as false , The rest is considered true .
Here is the set of binary comparison operations defined as functions :
eq If arg1 == arg2 Then return to true
ne If arg1 != arg2 Then return to true
lt If arg1 < arg2 Then return to true
le If arg1 <= arg2 Then return to true
gt If arg1 > arg2 Then return to true
ge If arg1 >= arg2 Then return to true
In order to simplify the multi parameter equality detection ,eq( Only eq) Acceptable 2 One or more parameters , It compares the first parameter with the rest in turn , Return the result of the following formula :
{{eq arg1 arg2 arg3}}
Comparison functions only apply to basic types ( Or redefined basic types , Such as ”type Celsius float32”). however , Integers and floating-point numbers cannot be compared with each other .
11, Custom function
Go The template supports custom functions .
main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
func f1(w http.ResponseWriter, r *http.Request) {
// Define a function kua
k := func(name string) (string, error) {
return name + " Young and handsome !", nil
}
t := template.New("f.tmpl") // Create a template object , The template name should correspond to the template file parsed below
// Tell the template engine , I now define a kua This function , This step should be done before parsing the template
t.Funcs(template.FuncMap{
"kua99": k,
})
_, err := t.ParseFiles("f.tmpl")
if err != nil {
fmt.Printf("parse template file failed, err:%v\n", err)
return
}
name := "eryajf"
// Apply colours to a drawing template
t.Execute(w, name)
}
func demo1(w http.ResponseWriter, r *http.Request) {
// Analytical template
t, err := template.ParseFiles("t.tmpl", "ul.tmpl") // Be careful : Nested templates should be placed behind
if err != nil {
fmt.Printf("parse template failed, err:%v\n", err)
return
}
// Apply colours to a drawing template
name := " Erya speaks Buddhism "
t.Execute(w, name)
}
func main() {
http.HandleFunc("/", f1)
http.HandleFunc("/tmpl", demo1)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Println("Http server start failed, err", err)
return
}
}
f.tmpl
<html lang="zh=CN">
<head>
<title> Custom function </title>
</head>
<body>
<p> {{ kua99 . }} </p>
</body>
</html>
t.tmpl
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>tmpl test</title>
</head>
<body>
<h1> Test nesting template grammar </h1>
<hr>
{{/* Nested another separate template file */}}
{{template "ul.tmpl"}}
<hr>
{{/* Nested a pass define Imported template file */}}
{{template "ol.tmpl"}}
</body>
<p> Hello {{ . }} </p>
</html>
{{ define "ol.tmpl"}}
<ol>
<li> having dinner </li>
<li> sleep </li>
<li> Doudou </li>
</ol>
{{end}}
ul.tmpl
<ul>
<li> notes </li>
<li> journal </li>
<li> test </li>
</ul>
We can do it in the template file hello.tmpl
Use our custom in the following way kua
Function .
{{kua .Name}}
12, nesting template
We can do it in template Nested other template. This template It can be a separate file , Or through define
Defined template.
for instance : t.tmpl
The contents of the document are as follows :
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>tmpl test</title>
</head>
<body>
<h1> Test nesting template grammar </h1>
<hr>
{{template "ul.tmpl"}}
<hr>
{{template "ol.tmpl"}}
</body>
</html>
{{ define "ol.tmpl"}}
<ol>
<li> having dinner </li>
<li> sleep </li>
<li> Doudou </li>
</ol>
{{end}}
ul.tmpl
The contents of the document are as follows :
<ul>
<li> notes </li>
<li> journal </li>
<li> test </li>
</ul>
Let's sign up for templDemo
Routing functions .
http.HandleFunc("/tmpl", tmplDemo)
tmplDemo
The specific content of the function is as follows :
func tmplDemo(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles("./t.tmpl", "./ul.tmpl")
if err != nil {
fmt.Println("create template failed, err:", err)
return
}
user := UserInfo{
Name: " The little prince ",
Gender: " male ",
Age: 18,
}
tmpl.Execute(w, user)
}
Be careful : When parsing a template , Nested templates must be parsed later , For example, in the example above t.tmpl
Nested in the template ul.tmpl
, therefore ul.tmpl
To be in t.tmpl
After the analysis .
13,block
{{block "name" pipeline}} T1 {{end}}
block
Is to define a template {{define "name"}} T1 {{end}}
And execution {{template "name" pipeline}}
abbreviation , A typical usage is to define a set of root templates , Then customize it by redefining the block template .
Define a root template templates/base.tmpl
, The contents are as follows :
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>Go Templates</title>
</head>
<body>
<div class="container-fluid">
{{block "content" . }}{{end}}
</div>
</body>
</html>
Then define a templates/index.tmpl
,” Inherit ”base.tmpl
:
{{template "base.tmpl"}}
{{define "content"}}
<div>Hello world!</div>
{{end}}
And then use template.ParseGlob
Parse template files according to regular matching rules , And then through ExecuteTemplate
Render the specified template :
func index(w http.ResponseWriter, r *http.Request){
tmpl, err := template.ParseGlob("templates/*.tmpl")
if err != nil {
fmt.Println("create template failed, err:", err)
return
}
err = tmpl.ExecuteTemplate(w, "index.tmpl", nil)
if err != nil {
fmt.Println("render template failed, err:", err)
return
}
}
If our template names conflict , For example, there is a..., defined under different business lines index.tmpl
Templates , We can solve this problem in the following two ways .
- Use... At the beginning of the template file
{{define Template name }}
Statement to explicitly name the template . - You can store the template file in
templates
In different directories under the folder , And then usetemplate.ParseGlob("templates/**/*.tmpl")
Analytical template .
14, Modify the default identifier
Go Curly braces used by the template engine of the standard library {{
and }}
As identification , And many front-end frameworks ( Such as Vue
and AngularJS
) Also used {{
and }}
As identifier , So when we use both Go There will be a conflict between the language template engine and the above front-end framework , At this time, we need to modify the identifier , Modify the front-end or modify Go Linguistic . Here's how to modify Go The default identifier of the language template engine :
template.New("test").Delims("{[", "]}").ParseFiles("./t.tmpl")
3,text/template And html/tempalte The difference between
html/template
It is aimed at the need to return HTML Content scene , Some risky content will be escaped during template rendering , In order to prevent cross site scripting attacks .
for example , I define the following template file :
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello</title>
</head>
<body>
{{.str1}}
{{.str2 | safe }}
</body>
</html>
At this time, a period of JS Code and use html/template
To render the file , The escaped... Will be displayed on the page JS Content . alert(' Hey, hey, hey ')
This is it. html/template
What you did for us .
But in some scenarios , If we believe what the user enters , If you don't want to escape , You can write a safe function , Manually return to a template.HTML
Type of content . Examples are as follows :
package main
import (
"fmt"
"html/template"
"net/http"
)
func index(w http.ResponseWriter, r *http.Request) {
t, err := template.New("index.tmpl").Funcs(template.FuncMap{
"safe": func(s string) template.HTML {
return template.HTML(s)
},
}).ParseFiles("./index.tmpl")
//t, err := template.ParseFiles("./index.tmpl")
if err != nil {
fmt.Printf("parse template failed, err:%v\n", err)
return
}
str1 := "<script>alert(123);</script>"
str2 := "<a href='http://eryajf.net'> Erya's blog about fan </a>"
t.Execute(w, map[string]string{
"str1": str1,
"str2": str2,
})
}
func main() {
http.HandleFunc("/index", index)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Println("Http server start failed, err", err)
return
}
}
In this way, we only need to use our defined after the content of the template file that does not need to be escaped safe Function is OK .
{{ . | safe }}
4, Load static file
First create two static files , Simulation project structure .
templates/posts/index.tmpl
{{define "posts/index.tmpl"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>posts/index</title>
</head>
<body>
{{ .title }}
</body>
</html>
{{end}}
templates/posts/index.tmpl
{{define "users/index.tmpl"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="/xxx/index.css">
<title>users/index</title>
</head>
<body>
{{ .title | safe }}
</body>
<script src="/xxx/index.js"></script>
</html>
{{end}}
Then you can uniformly quote , One r.LoadHTMLGlob("templates/**/*")
, One r.Static("xxx", "static")
package main
import (
"github.com/gin-gonic/gin"
"html/template"
"net/http"
)
func main() {
r := gin.Default()
// Load static file
r.Static("xxx", "static")
// gin Add custom functions to the template in the framework
r.SetFuncMap(template.FuncMap{
"safe": func(str string) template.HTML {
return template.HTML(str)
},
})
//r.LoadHTMLFiles("templates/index.tmpl") // Template parsing
r.LoadHTMLGlob("templates/**/*")
r.GET("/posts/index", func(c *gin.Context) {
// HTTP request
c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{ // Template rendering
"title": "posts page",
})
})
r.GET("/users/index", func(c *gin.Context) {
// HTTP request
c.HTML(http.StatusOK, "users/index.tmpl", gin.H{ // Template rendering
"title": "<a href='http://eryajf.net'> Erya's blog about fan </a>",
})
})
r.GET("home", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
r.Run(":9090") // start-up server
}
边栏推荐
- kali局域网ARP欺骗(arpspoof)并监听(mitmproxy)局域内其它主机上网记录
- 数据库全量SQL分析与审计系统性能优化之旅
- Review of MySQL (10): three paradigms of database
- Double non grind one, three side byte, cool. Next time
- A story on the cloud of the Centennial Olympic Games belonging to Alibaba cloud video cloud
- ISCC2022
- Why my order by create_ Time ASC becomes order by ASC
- [matrix theory & graph theory] final exam review mind map
- Have a meal, dry pot, fat intestines + palm treasure!
- Leetcode 494. Objectives and
猜你喜欢
基于Halcon的螺栓螺丝部分划痕、腐蚀缺陷检测
超级重磅!Apache Hudi多模索引对查询优化高达30倍
Quickly copy the request in browser F12 to postman/ or generate the corresponding code of the relevant language
leetcode:6095. 强密码检验器 II【简单模拟 + 不符合直接False】
Kali implements port forwarding through iptables
收获满满的下午
Start with no place to live
leetcode:6097. 替换字符后匹配【set记录 + 相同长度逐一查询】
MySQL advanced learning notes
从应无所住说起
随机推荐
数据库全量SQL分析与审计系统性能优化之旅
实验10 Bezier曲线生成-实验提高-控制点生成B样条曲线
国内如何下载ProxyStrike
【5GC】三种SSC(Session and Service Continuity)模式介绍
机器学习在美团配送系统的实践:用技术还原真实世界-笔记
Why my order by create_ Time ASC becomes order by ASC
To understand Devops, you must read these ten books!
leetcode:5289. 公平分发饼干【看数据范围 + dfs剪枝】
Redis中的事务
leetcode:6097. 替换字符后匹配【set记录 + 相同长度逐一查询】
Shenzhen has been shut down for 7 days since March 14. Home office experience | community essay solicitation
吃饭咯 干锅肥肠 + 掌中宝!
YOLOX网络结构详解
Experiment 10 Bezier curve generation - experiment improvement - interactive generation of B-spline curve
leetcode:6094. 公司命名【分组枚举 + 不能重复用set交集 + product笛卡儿积(repeat表示长度)】
Istio 1.14 发布
Leetcode 1049. Weight of the last stone II
leetcode:98. Count the number of subarrays whose score is less than k [double pointers + number of calculated subsets + de duplication]
OpenGL shadow implementation (soft shadow)
Hugo 博客搭建教程