当前位置:网站首页>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
边栏推荐
- Task6: using transformer for emotion analysis
- Kivy教程之 如何自动载入kv文件
- The principle of human voice transformer
- 服务器硬盘冷迁移后网卡无法启动问题
- PhpMyAdmin stage file contains analysis traceability
- Can newly graduated European college students get an offer from a major Internet company in the United States?
- The network card fails to start after the cold migration of the server hard disk
- Resource Cost Optimization Practice of R & D team
- The reasons why there are so many programming languages in programming internal skills
- Open PHP error prompt under Ubuntu 14.04
猜你喜欢
![[sort] bucket sort](/img/52/95514b5a70cea75821883e016d8adf.jpg)
[sort] bucket sort
[email protected] chianxin: Perspective of Russian Ukrainian cyber war - Security confrontation and sanctions g"/>Start signing up CCF C ³- [email protected] chianxin: Perspective of Russian Ukrainian cyber war - Security confrontation and sanctions g

Setting up remote links to MySQL on Linux

Box layout of Kivy tutorial BoxLayout arranges sub items in vertical or horizontal boxes (tutorial includes source code)
![[技術發展-24]:現有物聯網通信技術特點](/img/f3/a219fe8e7438b8974d2226b4c3d4a4.png)
[技術發展-24]:現有物聯網通信技術特點

MySQL installation, uninstallation, initial password setting and general commands of Linux

挡不住了,国产芯片再度突进,部分环节已进到4nm

Go language unit test 3: go language uses gocovey library to do unit test

mysql更新时条件为一查询

DQL basic query
随机推荐
SQL Injection (AJAX/JSON/jQuery)
MySQL_ JDBC
R language uses the data function to obtain the sample datasets available in the current R environment: obtain all the sample datasets in the datasets package, obtain the datasets of all packages, and
[technology development-24]: characteristics of existing IOT communication technology
MySQL installation, uninstallation, initial password setting and general commands of Linux
掌握Cypress命令行选项,是真正掌握Cypress的基础
Libuv库 - 设计概述(中文版)
[how to earn a million passive income]
双向链表(我们只需要关注插入和删除函数)
User and group command exercises
记录关于银行回调post请求405 问题
Mysql database basic operation - regular expression
Road construction issues
CVPR 2022 | interpretation of 6 excellent papers selected by meituan technical team
[redis] cache warm-up, cache avalanche and cache breakdown
【BW16 应用篇】安信可BW16模组与开发板更新固件烧录说明
Logseq 评测:优点、缺点、评价、学习教程
AI 考高数得分 81,网友:AI 模型也免不了“内卷”!
Smbms project
Logseq evaluation: advantages, disadvantages, evaluation, learning tutorial