当前位置:网站首页>Golang — template
Golang — template
2022-07-03 13:47:00 【The wind blows on the edge of the cloud】
List of articles
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 use UTF8 code .
- Use in template file { { and }} Packages and identification need incoming data .
- The data passed to the template can be passed through the dot . 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 .
Template syntax
{ { and }} The contents of the package are collectively referred to as action, There are two types :
- Data evaluation (data evaluations)
- Control structure (control structures)
action The result of the evaluation will be copied directly into the template , Control structure and we write Go The procedure is similar , It is also a conditional statement 、 Loop statement 、 Variable 、 Function calls and so on …
1. notes
{
{
/* a comment */}}
// notes , The execution ignores . You can do more . Comments cannot be nested , And it has to be close to the boundary .
2. Remove spaces
stay { { Add a dash after the symbol and leave one or more spaces to divide the white space in front of it ( Include line breaks 、 tabs 、 Spaces, etc. ), namely { {- xxxx.
stay }} Add one or more spaces and a dash in front of - Come and go, divide the blank behind it , namely xxxx -}}.
<p>{
{ 20 }} < {
{ 40 }}</p> // 20 < 40
<p>{
{ 20 -}} < {
{- 40 }}</p> // 20<40
3. The Conduit pipeline
pipeline It refers to the operation of generating data . such as { {.}}、{ {.Name}}、funcname args etc. .
You can use pipe symbols | Link multiple commands , Usage and unix The pipe under the pipe is similar :| The previous command will calculate the result ( Or return value ) The last position passed to the next command .
{
{"put" | printf "%s%s" "out" | printf "%q"}} // "output"
4. Variable
stay golang Rendering template When , You can accept a interface{} Variable of type , We can read the values in the variables in the template file and render them to the template .
{ { and }} In the middle of the . Represents the incoming variable ( data ), It represents the current object of the current scope , Variable ( data ) Different renderings are different .
There are two commonly used types of incoming variables . One is struct, This can be read in the template struct Field of ( The nature of exposure ) To render . The other one is map[string]interface{}, You can use... In the template key Get the corresponding value To render .
Sample code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p> full name :{
{ .Name }}</p>
<p> Age :{
{ .Age }}</p>
<p> Gender :{
{ .Gender }}</p>
<p> Chinese achievement :{
{ .Score.yuwen}}</p>
<p> Math scores :{
{ .Score.shuxue}}</p>
<p> English scores :{
{ .Score.yingyu}}</p>
</body>
</html>
package main
import (
"fmt"
"html/template"
"net/http"
)
// User Structure
type User struct {
Name string
Age int
Gender string
Score map[string]float64
}
func indexHandleFunc(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("./index.tmpl")
if err != nil {
fmt.Println("template parsefiles failed, err:", err)
return
}
user := User{
Name: "ruby",
Age: 20,
Gender: "female",
Score: map[string]float64{
"yuwen": 98,
"shuxue": 100,
"yingyu": 94,
},
}
t.Execute(w, user)
}
func main() {
http.HandleFunc("/", indexHandleFunc)
http.ListenAndServe(":8080", nil)
}
Custom variable
{
{
$obj := "jack" }}
{
{
$obj }} // Output :jack
5. function
golang In fact, the function of the template is very limited , Many complex logic cannot be expressed directly by using template syntax , So we can only use template functions to realize .
First ,template When the package creates a new template , Support .Funcs Method to import the custom function collection into the template , Subsequent files rendered through this template support calling these functions directly .
This function set is defined as :
type FuncMap map[string]interface{
}
key For the name of the method ,value It's a function . There is no limit to the number of arguments of the function , But there are restrictions on the return value . There are two options , One is that there is only one return value , There are also two return values , But the second return value must be error Type of . The difference between these two functions is that when the second function is called in the template , Suppose the return of the second parameter of the template function is not empty , The rendering step will be interrupted and an error will be reported .
Built in template functions :
var builtins = FuncMap{
// Return the first null parameter or the last parameter . You can have as many parameters as you want .
// "and x y" Equivalent to "if x then y else x"
"and": and,
// Explicitly call functions . The first argument must be a function type , It's not template The function in , It's an external function .
// For example, one struct A field in is func Type of .
// "call .X.Y 1 2" Represents a call to dot.X.Y(1, 2),Y Must be func type , The argument to the function is 1 and 2.
// Function must have only one or 2 Return values , If there is a second return value , Must be error type .
"call": call,
// Returns an escape equivalent to the text representation of its argument HTML.
// This function is in the html/template Unavailable in .
"html": HTMLEscaper,
// Index indexable objects . The first parameter is the index object , The following parameter is the index bit .
// "index x 1 2 3" It stands for x[1][2][3].
// Indexable objects include map、slice、array.
"index": index,
// Returns an escape equivalent to the text representation of its argument JavaScript.
"js": JSEscaper,
// Returns the length.
"len": length,
// Boolean negation . Only one parameter is allowed .
"not": not,
// Return the first non empty parameter or the last parameter . You can have as many parameters as you want .
// "or x y" Equivalent to "if x then x else y".
"or": or,
"print": fmt.Sprint,
"printf": fmt.Sprintf,
"println": fmt.Sprintln,
// 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 .
"urlquery": URLQueryEscaper,
}
Comparison function :
eq arg1 arg2:
arg1 == arg2 When is true
ne arg1 arg2:
arg1 != arg2 When is true
lt arg1 arg2:
arg1 < arg2 When is true
le arg1 arg2:
arg1 <= arg2 When is true
gt arg1 arg2:
arg1 > arg2 When is true
ge arg1 arg2:
arg1 >= arg2 When is true
Custom template functions
t = t.Funcs(template.FuncMap{
"handleFieldName": HandleFunc})
Function call
{
{
funcname .arg1 .arg2}}
6. conditional
{
{
if pipeline }} T1 {
{
end }}
{
{
if pipeline }} T1 {
{
else }} T2 {
{
end }}
{
{
if pipeline }} T1 {
{
else if pipeline }} T2 {
{
end }}
7. Loop traversal
{
{
range pipeline }} T1 {
{
end }}
// If pipeline The length of is 0 The output else The content in
{
{
range pipeline }} T1 {
{
else }} T2 {
{
end }}
range Traversable slice、 Array 、map or channel. When traversing , Will be set . For the element currently being traversed .
For the first expression , When the value of traversal object is 0 When the value of , be range Just skip , It's like if equally . For the second expression , Then it traverses to 0 Execute when value else.
range The parameter part of is pipeline, Therefore, the value can be assigned in the process of iteration . But there are two cases of assignment :
{
{
range $value := pipeline }} T1 {
{
end }}
{
{
range $key, $value := pipeline }} T1 {
{
end }}
If range Is assigned to only one variable , Then this variable is the value of the element currently being traversed . If you assign values to two variables , Then the first variable is the index value (array/slice Numerical value ,map yes key), The second variable is the value of the element currently being traversed .
8. with…end
{
{
with pipeline }} T1 {
{
end }}
{
{
with pipeline }} T1 {
{
else }} T0 {
{
end }}
For the first format , When pipeline Not for 0 When it's worth it , take . Set to pipeline The value of the operation , Otherwise, skip .
For the second format , When pipeline by 0 When the value of , perform else Sentence block T0, otherwise . Set to pipeline The value of the operation , And implement T1.
9. Template nesting
define
define You can define a template directly in the content to be parsed// The definition is name Of template { { define "name" }} T { { end }}
template
Use template To execute the template// Execution name is name Of template { { template "name" }} { { template "name" pipeline }}
block
{ { block "name" pipeline }} T { { end }}
block Equivalent to define Define a name name The template of , And in " Yes " Where to execute this template , At the time of execution . Set to pipeline Value .
Equivalent to : First { { define “name” }} T { { end }} Re execution { { template “name” pipeline }}.
Code example :
<!-- index.tmpl -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{
{ template "content"}}
</body>
</html>
<!-- red.tmpl -->
{
{ define "content" }}
<div style="color:red"><h3>hello world</h3></div>
{
{ end }}
<!-- blue.tmpl -->
{
{ define "content" }}
<div style="color:blue"><h3>hello world</h3></div>
{
{ end }}
// main.go
package main
import (
"html/template"
"math/rand"
"net/http"
"time"
)
func indexHandleFunc(w http.ResponseWriter, r *http.Request) {
t := template.New("index.tmpl")
rand.Seed(time.Now().UnixNano())
if rand.Intn(100) > 50 {
t, _ = template.ParseFiles("./index.tmpl", "./red.tmpl")
} else {
t, _ = template.ParseFiles("./index.tmpl", "./blue.tmpl")
}
t.Execute(w, "")
}
func main() {
http.HandleFunc("/", indexHandleFunc)
http.ListenAndServe(":8080", nil)
}
If you use block, Then you can set the default content Templates .
modify index.tmpl
<!-- index.tmpl -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{
{ block "content" . }}
<div style="color:yellow"><h3>hello world</h3></div>
{
{ end }}
</body>
</html>
Modify the backend program :
// main.go
package main
import (
"html/template"
"math/rand"
"net/http"
"time"
)
func indexHandleFunc(w http.ResponseWriter, r *http.Request) {
t := template.New("index.tmpl")
rand.Seed(time.Now().UnixNano())
if rand.Intn(100) > 75 {
t, _ = template.ParseFiles("./index.tmpl", "./red.tmpl")
} else if rand.Intn(100) > 25 {
t, _ = template.ParseFiles("./index.tmpl", "./blue.tmpl")
} else {
t, _ = template.ParseFiles("./index.tmpl")
}
t.Execute(w, "")
}
func main() {
http.HandleFunc("/", indexHandleFunc)
http.ListenAndServe(":8080", nil)
}
10. Template inheritance
adopt block、define、template Implement template inheritance .
Sample code :
<!-- base.tmpl -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style> .head {
height: 50px; background-color: red; width: 100%; text-align: center; } .main {
width: 100%; } .main .left {
width: 30%; height: 1000px; float: left; background-color:violet; text-align: center; } .main .right {
width: 70%; float: left; text-align: center; height: 1000px; background-color:yellowgreen; } </style>
</head>
<body>
<div class="head">
<h1>head</h1>
</div>
<div class="main">
<div class="left">
<h1>side</h1>
</div>
<div class="right">
{
{ block "content" . }}
<h1>content</h1>
{
{ end }}
</div>
</div>
</body>
</html>
<!-- index.tmpl -->
{
{ template "base.tmpl" . }}
{
{ define "content" }}
<h1> This is a index page </h1>
{
{ . }}
{
{ end }}
<!-- home.tmpl -->
{
{ template "base.tmpl" . }}
{
{ define "content" }}
<h1> This is a home page </h1>
{
{ . }}
{
{ end }}
// main.go
package main
import (
"html/template"
"net/http"
)
func indexHandleFunc(w http.ResponseWriter, r *http.Request) {
t := template.New("index.tmpl")
t, _ = t.ParseFiles("./base.tmpl", "./index.tmpl")
t.Execute(w, "index")
}
func homeHandleFunc(w http.ResponseWriter, r *http.Request) {
t := template.New("home.tmpl")
t, _ = t.ParseFiles("./base.tmpl", "./home.tmpl")
t.Execute(w, "home")
}
func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/index", indexHandleFunc)
http.HandleFunc("/home", homeHandleFunc)
server.ListenAndServe()
}
11. 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")
12. html/template Context aware
about html/template package , There is a very useful function : Context awareness .text/template There is no such function .
Context awareness refers specifically to the context css、js、html、url Of path、url Of query, Automatically escape in different formats .
Sample code
<!-- index.tmpl -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>{
{ . }}</div>
</body>
</html>
// main.go
package main
import (
// "text/template"
"html/template"
"net/http"
)
func indexHandleFunc(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("./index.tmpl")
data := `<script>alert("helloworld")</script>`
t.Execute(w, data)
}
func main() {
http.HandleFunc("/", indexHandleFunc)
http.ListenAndServe(":8080", nil)
}
Run the program , Page shows :
<script>alert("helloworld")</script>
No escape
Context aware automatic escape can make the program more secure , For example, to prevent XSS attack ( For example, enter the content with in the form and submit , Will make this part submitted by users script Be performed ).
If you really don't want to escape , You can do type conversion .
type CSS
type HTML
type JS
type URL
Write a custom template function , Realize the type conversion of content .
Sample code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>{
{ .str1 }}</div>
<div>{
{ .str2 | safe }}</div>
</body>
</html>
package main
import (
// "text/template"
"html/template"
"net/http"
)
func indexHandleFunc(w http.ResponseWriter, r *http.Request) {
t := template.New("index.tmpl")
t.Funcs(template.FuncMap{
"safe": func(str string) template.HTML {
return template.HTML(str)
},
}).ParseFiles("./index.tmpl")
m := map[string]interface{
}{
"str1": `<script>alert("helloworld")</script>`,
"str2": `<a href = "http://baidu.com">baidu</a>`,
}
t.Execute(w, m)
}
Reference documents :
【go Language learning 】 Standard library template
边栏推荐
- Golang — 命令行工具cobra
- Start signing up CCF C ³- [email protected] chianxin: Perspective of Russian Ukrainian cyber war - Security confrontation and sanctions g
- Red Hat Satellite 6:更好地管理服务器和云
- Unity render streaming communicates with unity through JS
- Software testing is so hard to find, only outsourcing offers, should I go?
- Multi table query of MySQL - multi table relationship and related exercises
- Kivy教程之 如何通过字符串方式载入kv文件设计界面(教程含源码)
- SQL Injection (GET/Select)
- Universal dividend source code, supports the dividend of any B on the BSC
- 常见的几种最优化方法Matlab原理和深度分析
猜你喜欢
【电脑插入U盘或者内存卡显示无法格式化FAT32如何解决】
CVPR 2022 | 美团技术团队精选6篇优秀论文解读
Kivy教程之 盒子布局 BoxLayout将子项排列在垂直或水平框中(教程含源码)
Logseq 评测:优点、缺点、评价、学习教程
Libuv库 - 设计概述(中文版)
研发团队资源成本优化实践
使用Tensorflow进行完整的深度神经网络CNN训练完成图片识别案例2
全面发展数字经济主航道 和数集团积极推动UTONMOS数藏市场
The principle of human voice transformer
Go language unit test 4: go language uses gomonkey to test functions or methods
随机推荐
Field problems in MySQL
Spark practice 1: build spark operation environment in single node local mode
[développement technologique - 24]: caractéristiques des technologies de communication Internet des objets existantes
Sequence table (implemented in C language)
[556. Next larger element III]
Introduction to the implementation principle of rxjs observable filter operator
顺序表(C语言实现)
Shell timing script, starting from 0, CSV format data is regularly imported into PostgreSQL database shell script example
File uploading and email sending
编程内功之编程语言众多的原因
Screenshot of the operation steps of upload labs level 4-level 9
[technology development-24]: characteristics of existing IOT communication technology
Kivy教程之 如何自动载入kv文件
静态链表(数组的下标代替指针)
NFT new opportunity, multimedia NFT aggregation platform okaleido will be launched soon
MySQL constraints
Leetcode-1175.Prime Arrangements
PowerPoint tutorial, how to save a presentation as a video in PowerPoint?
SQL Injection (POST/Search)
untiy世界边缘的物体阴影闪动,靠近远点的物体阴影正常