当前位置:网站首页>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
边栏推荐
- [quantitative trading] permanent portfolio, turtle trading rules reading, back testing and discussion
- Unity render streaming communicates with unity through JS
- 树的深入和广度优先遍历(不考虑二叉树)
- 用户和组命令练习
- SQL Injection (POST/Select)
- 顺序表(C语言实现)
- windos 创建cordova 提示 因为在此系统上禁止运行脚本
- mysql中的字段问题
- [how to earn a million passive income]
- Father and basketball
猜你喜欢
PowerPoint 教程,如何在 PowerPoint 中將演示文稿另存為視頻?
Mysql database basic operation - regular expression
AI scores 81 in high scores. Netizens: AI model can't avoid "internal examination"!
Flutter dynamic | fair 2.5.0 new version features
Multi table query of MySQL - multi table relationship and related exercises
MySQL_ JDBC
Several common optimization methods matlab principle and depth analysis
Flutter dynamic | fair 2.5.0 new version features
JSP and filter
AI 考高数得分 81,网友:AI 模型也免不了“内卷”!
随机推荐
The principle of human voice transformer
实现CNN图像的识别和训练通过tensorflow框架对cifar10数据集等方法的处理
Disruptor -- a high concurrency and high performance queue framework for processing tens of millions of levels
MySQL functions and related cases and exercises
The shortage of graphics cards finally came to an end: 3070ti for more than 4000 yuan, 2000 yuan cheaper than the original price, and 3090ti
mysql更新时条件为一查询
Stack application (balancer)
Unity render streaming communicates with unity through JS
Comprehensive evaluation of double chain notes remnote: fast input, PDF reading, interval repetition / memory
JSP and filter
Tutoriel PowerPoint, comment enregistrer une présentation sous forme de vidéo dans Powerpoint?
双向链表(我们只需要关注插入和删除函数)
Mycms we media mall v3.4.1 release, user manual update
编程内功之编程语言众多的原因
The R language GT package and gtextras package gracefully and beautifully display tabular data: nflreadr package and gt of gtextras package_ plt_ The winloss function visualizes the win / loss values
Asp. Net core1.1 without project JSON, so as to generate cross platform packages
Replace the GPU card number when pytorch loads the historical model, map_ Location settings
Libuv Library - Design Overview (Chinese version)
【BW16 应用篇】安信可BW16模组与开发板更新固件烧录说明
研发团队资源成本优化实践