当前位置:网站首页>Golang template (text/template)
Golang template (text/template)
2022-06-30 13:31:00 【It workers】
text/template yes Go Language standard library , Implement data-driven templates to generate text output , It can be understood that one group of text is dynamically embedded into another group of text according to a specific format .
There is another process html Template for text (html/template), You can understand what you are interested in .
Simple characters
Example
package main
import (
"os"
"text/template"
)
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
name := "world"
tmpl, err := template.New("test").Parse("hello, {{.}}") // Create a template , The content is "hello, {{.}}"
CheckErr(err)
err = tmpl.Execute(os.Stdout, name) // take string Synthesis with template , Variable name The content will be replaced by {{.}}
// Put the synthesis results in os.Stdout in Output
CheckErr(err)
}Output : hello, world
The input text of the template is in any format UTF-8 Code text . {{ 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 …
Successfully parsed the template (Parse) after , Can be used safely in a concurrent environment , If output to the same io.Writer Data may overlap ( Because the sequence of concurrent execution cannot be guaranteed ).
here {{ and }} The middle period (.) Represents the incoming data , Different data render differently , Can represent go Any type in a language , Like a structure 、 Hash, etc .
struct
Example
package main
import (
"os"
"text/template"
)
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
type Inventory struct {
Material string
Count uint
}
sweaters := Inventory{"wool", 17}
tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
CheckErr(err)
err = tmpl.Execute(os.Stdout, sweaters)
CheckErr(err)
}Output :17 items are made of wool
Template file
Create a new template file demo.go.tpl
Content
{{.Count}} items are made of {{.Material}}
The above example can be changed to
package main
import (
"os"
"text/template"
)
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
type Inventory struct {
Material string
Count uint
}
sweaters := Inventory{"wool", 17}
tmpl, err := template.ParseFiles("demo.go.tpl")
CheckErr(err)
err = tmpl.Execute(os.Stdout, sweaters)
CheckErr(err)
}Output :17 items are made of wool
Multiple templates
Example
package main
import (
"fmt"
"os"
"text/template"
)
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
type Inventory struct {
Material string
Count uint
}
sweaters := Inventory{"wool", 17}
tmpl, err := template.New("T2").Parse("{{.Count}} items are made of")
tmpl, err = tmpl.New("test").Parse("{{.Count}} items are made of {{.Material}}")
CheckErr(err)
err = tmpl.ExecuteTemplate(os.Stdout, "T2", sweaters) // You can select a template
CheckErr(err)
fmt.Println("")
fmt.Println(tmpl.Name())
tmpl = tmpl.Lookup("test") // Switch templates , There must be a return , Otherwise it doesn't work
fmt.Println(tmpl.Name())
}Output :
17 items are made of
test
test
Output to specified file
Example
package main
import (
"os"
"text/template"
)
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
type Inventory struct {
Material string
Count uint
}
sweaters := Inventory{"wool", 17}
tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
CheckErr(err)
file, err := os.OpenFile("demo.txt", os.O_CREATE|os.O_WRONLY, 0755)
CheckErr(err)
err = tmpl.Execute(file, sweaters)
CheckErr(err)
}Open file demo.txt, The content is : 17 items are made of wool
Cyclic operation
Usage method
{{range .Field}}
{{.ChildFieldOne}} -- {{.ChildFieldTwo }}
{{ end }}
Example
package main
import (
"os"
"text/template"
)
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
type Inventory struct {
Material string
Count uint
}
type NewInventory struct {
Fields []Inventory
}
sweaters := NewInventory{
Fields: []Inventory{
Inventory{Material: "wool", Count: 19},
Inventory{Material: "wooltwo", Count: 20},
}}
var Text = `
{{range .Fields }}
Material: {{.Material}} - Count:{{.Count}}
{{ end }}
`
tmpl, err := template.New("test").Parse(Text)
CheckErr(err)
err = tmpl.Execute(os.Stdout, sweaters)
CheckErr(err)
}template function
namely : You can use function operations on a field . For slightly more complex field processing .
type FuncMap map[string]interface{}
t = t.Funcs(template.FuncMap{"handleFieldName": HandleFunc})
Built in template functions :
var builtins = FuncMap{
"and": and,
"call": call,
"html": HTMLEscaper,
"index": index,
"js": JSEscaper,
"len": length,
"not": not,
"or": or,
"print": fmt.Sprint,
"printf": fmt.Sprintf,
"println": fmt.Sprintln,
"urlquery": URLQueryEscaper,
}Example
package main
import (
"os"
"text/template"
)
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
type Inventory struct {
Material string
Count uint
}
type NewInventory struct {
Fields []Inventory
}
sweaters := NewInventory{
Fields: []Inventory{
Inventory{Material: "wool", Count: 19},
Inventory{Material: "wooltwo", Count: 20},
}}
var Text = `
{{range .Fields }}
Material: {{.Material | handleString}} - Count:{{.Count | handleInt }}
{{ end }}
`
tmpl, err := template.New("test").Funcs(template.FuncMap{"handleString": handleString, "handleInt": handleInt}).Parse(Text)
CheckErr(err)
err = tmpl.Execute(os.Stdout, sweaters)
CheckErr(err)
}
func handleInt(number uint) uint {
return number + 10
}
func handleString(field string) string {
return " string is: " + field
}Output :
Material: string is: wool - Count:29
Material: string is: wooltwo - Count:30
Actions
notes
{{*/\* comment \*/*}}
Crop spaces
// tailoring content Space before and after
{{- content -}}
// tailoring content The space in front of it
{{- content }}
// tailoring content Space after
{{ content -}}
Pipeline functions
usage 1:
{{FuncName1}}
This tag will call with the name “FuncName1” Template function of ( Equivalent to the execution of “FuncName1()”, No parameters are passed ) And output its return value .
usage 2:
{{FuncName1 " Parameter values 1" " Parameter values 2"}}
This tag will call “FuncName1(" Parameter values 1", " Parameter values 2")”, And output its return value
usage 3:
{{.Admpub|FuncName1}}
This tag will call with the name “FuncName1” Template function of ( Equivalent to the execution of “FuncName1(this.Admpub)”, Place vertical bar “|” Sinister “.Admpub” Variable values are passed as function parameters ) And output its return value .
Text output
{{ pipeline }}
pipeline The data represented will be generated and called fmt.Print Function similar output , For example, integer type 3 It will be converted to a string “3” Output .
Conditional statements
{{ if pipeline }} T1 {{ end }}
{{ if pipeline }} T1 {{ else }} T0 {{ end }}
{{ if pipeline }} T1 {{ else if pipeline }} T0 {{ end }}
*// The grammar above is actually the abbreviation of the following *
{{ if pipeline }} T1 {{ else }}{{ if pipeline }} T0 { {end }}{{ end }}
{{ if pipeline }} T1 {{ else if pipeline }} T2 {{ else }} T0 {{ end }}
Loop statement
{{ range pipeline }} T1 {{ end }}
*// This else It's interesting , If pipeline The length of is 0 The output else The content in *
{{ range pipeline }} T1 {{ else }} T0 {{ end }}
*// Get the subscript of the container *
{{ range $index, $value := pipeline }} T1 {{ end }}
pipeline The value of must be an array 、 section 、 One of dictionaries and channels , That is, the value of the iteration type , Output multiple... According to the length of the value T1.
define
{{ define "name" }} T {{ end }}
The definition is named name The template of .
template
{{ template "name" }}
{{ template "name" pipeline }}
The reference is named name The template of .
block
{{ block "name" pipeline }} T1 {{ end }}
block The semantics of is if there is a named name The template of , Just reference and execute , If not named name The template of , Is to execute the content defined by yourself .
That is to say, we have made an extra step to judge whether the template exists , Render different content according to this result .
with
{{ with pipeline }} T1 {{ end }}
// If pipeline If it is a null value, output T0
{{ with pipeline }} T1 {{ else }} T0 {{ end }}
{{ with arg }}
. // here . Namely arg
{{ end }}
with Create a new context , In this environment . With the outside . irrelevant .
Parameters
The value of a parameter can take many forms , Any type can be evaluated , Include function 、 The pointer ( The pointer will automatically take an indirect value to the original value ):
Boolean 、 character string 、 character 、 Floating point numbers 、 The act of plural and Go similar
keyword nil representative go In language nil
Character period . Results representing values
With $ A variable that begins with a character is the corresponding value of the variable
The fields of the structure are represented as .Field, The result is Field Value , Support chain calls .Field1.Field2
Dictionary key Expressed as .Key The result is Key Corresponding value
If it is a method in the method set of structure .Method The result is the value returned after the method call (The result is the value of invoking the method with dot as the receiver)**
The method either has only one return value of any type or the second return value is error, No more , If error Not for nil, Will report an error directly , Stop template rendering
The result of the method call can continue the chain call .Field1.Key1.Method1.Field2.Key2.Method2
Declaring a variable method set can also call $x.Method1.Field
Group calls with parentheses print (.Func1 arg1) (.Func2 arg2) or (.StructValuedMethod "arg").Field
Variable
action Medium pipeline You can initialize variables to store results , The grammar is very simple :
$variable = pipeline
here , This action Declared a variable without producing any output .
range A loop can declare two variables :
range $index, $element := pipeline
stay if、with and range in , The scope of variables is extended to {{ end }} Where it is .
If it is not a control structure , The scope of the declared variables will be extended to the entire template .
For example, declare variables at the beginning of the template :
{{ $pages := .pagination.Pages }}
{{ $current := .pagination.Current }}
At the beginning of rendering ,$ The variable will be replaced with . Initial value , for example $pages Will be replaced by .pagenation.Pages. So cross references between templates do not pass variables , Variables only work in a specific scope .
function
When the template is rendered, it will find the function in two places :
Custom functions map
Global function map, These functions are built into the template
Custom functions use func (t *Template) Funcs(funcMap FuncMap) *Template register .
Global function list :
and
Return between parameters and The result of a Boolean operation , In fact, that is JavaScript Logical operators in &&, Returns the first one that can be converted to false Value , stay Go Medium is zero , If it's all for true Returns the last value .
tpl := "{{ and .x .y .z }}"
t, _ := template.New("test").Parse(tpl)
t.Execute(os.Stdout, map[string]interface{}{
"x": 1,
"y": 0,
"z": 3,
})output:
0
o
Logical operators ||, Returns the first one that can be converted to true Value , stay Go Is a non-zero value , If it's all for false Returns the last value .
tpl := "{{ or .x .y .z }}"
t, _ := template.New("test").Parse(tpl)
t.Execute(os.Stdout, map[string]interface{}{
"x": 1,
"y": 0,
"z": 3,
})
output:
1
call
Returns the result of calling the first function parameter , Function must have one or two return values ( The second return value must be error, If the value is not nil Will stop the template rendering )
tpl := "call: {{ call .x .y .z }} \n"
t, _ := template.New("test").Parse(tpl)
t.Execute(os.Stdout, map[string]interface{}{
"x": func(x, y int) int { return x+y},
"y": 2,
"z": 3,
})output:
5
html
Returns the escaped HTML character string , This function can't be in html/template Use in .
js
Returns the escaped JavaScript character string .
index
The first parameter is array、slice、map When using , Returns the value of the corresponding subscript .
index x 1 2 3 be equal to x[1][2][3].
len
Returns the length of the composite type .
not
Returns the opposite value of a Boolean parameter .
be equal to fmt.Sprint.
printf
be equal to fmt.Sprintf.
println
be equal to fmt.Sprintln.
urlquery
On the string url Query escape , Can't be in html/template The package uses .
// URLQueryEscaper returns the escaped value of the textual representation of
// its arguments in a form suitable for embedding in a URL query.
func URLQueryEscaper(args ...interface{}) string {
return url.QueryEscape(evalArgs(args))
}From the source code, you can see that this function directly calls url.QueryEscape Escape a string , There is no mystery .
Comparison function
eq: ==
ge: >=
gt: >
le: <=
lt: <
ne: !=Analyze two source codes :
// eq evaluates the comparison a == b || a == c || ...
func eq(arg1 reflect.Value, arg2 ...reflect.Value) (bool, error) {
v1 := indirectInterface(arg1)
k1, err := basicKind(v1)
if err != nil {
return false, er
}
if len(arg2) == 0 {
return false, errNoComparison
}
for _, arg := range arg2 {
v2 := indirectInterface(arg)
k2, err := basicKind(v2)
if err != nil {
return false, er
}
truth := false
if k1 != k2 {
// Special case: Can compare integer values regardless of type's sign.
switch {
case k1 == intKind && k2 == uintKind:
truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
case k1 == uintKind && k2 == intKind:
truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
default:
return false, errBadComparison
}
} else {
switch k1 {
case boolKind:
truth = v1.Bool() == v2.Bool()
case complexKind:
truth = v1.Complex() == v2.Complex()
case floatKind:
truth = v1.Float() == v2.Float()
case intKind:
truth = v1.Int() == v2.Int()
case stringKind:
truth = v1.String() == v2.String()
case uintKind:
truth = v1.Uint() == v2.Uint()
default:
panic("invalid kind")
}
}
if truth {
return true, nil
}
}
return false, nil
}
// ne evaluates the comparison a != b.
func ne(arg1, arg2 reflect.Value) (bool, error) {
// != is the inverse of ==.
equal, err := eq(arg1, arg2)
return !equal, er
}eq First, determine whether the interface types are equal , Then determine whether the values are equal , Nothing special .
ne It is a simple call eq, Then reverse .
ge、gt、le、lt And eq similar , Judge the type first , Then judge the size .
Nesting templates
Here's a more complex example :
// Load template
template.ParseFiles("templates/")
// Load multiple templates into a namespace ( Modules of the same namespace can refer to each other )
template.ParseFiles("header.tmpl", "content.tmpl", "footer.tmpl")
// must When the load fails panic
tmpl := template.Must(template.ParseFiles("layout.html"))
// Execute the loaded template file , Default to the first
tmpl.Execute(w, "test")
// If tmpl There are many templates in , You can specify the name of the template to execute
tmpl.ExecuteTemplate(w, "layout", "Hello world")
ExecuteTemplate The specified name is in the template file define "name" Of name.
Reference resources :
https://golang.org/pkg/text/template/
边栏推荐
- 一文讲清楚什么是类型化数组、ArrayBuffer、TypedArray、DataView等概念
- On the simplification and acceleration of join operation
- Clearing TinyMCE rich text cache in elementui
- Golang foundation -- slicing several declaration methods
- Apache Doris Compaction優化百科全書
- 【系统分析师之路】第五章 复盘软件工程(软件过程改进)
- Introduction to the new source code of substrat: fix the memory leak of the mission engine of beefy, and optimize the smart contract deletion queue
- Tronapi wave field interface PHP version - interface document attached - package based on thinkphp5 - source code without encryption - can be opened in two - detailed guidance of the author - 11:49:56
- 可观测,才可靠:云上自动化运维CloudOps系列沙龙 第一弹
- Open source of xinzhibao applet
猜你喜欢

单元测试效率优化:为什么要对程序进行测试?测试有什么好处?
![[deep anatomy of C language] storage principle of float variable in memory & comparison between pointer variable and](/img/3d/5d7fafba4ff7903afbd51d6d58dcdf.png)
[deep anatomy of C language] storage principle of float variable in memory & comparison between pointer variable and "zero value"

SQL考勤统计月报表

Apache Doris Compaction优化百科全书

【刷题篇】供暖器

【精选】资源变现资讯、新闻、自媒体、博客小程序(可引流,开通流量主,带pc后台管理)

Wechat applet reports an error: typeerror: cannot read property 'SetData' of undefined

可觀測,才可靠:雲上自動化運維CloudOps系列沙龍 第一彈
![[Select] resource realization information, news, we media, blog applet (can be drained, open traffic master, with PC background management)](/img/e7/1c34d8aa364b944688ec2ffb4feb7c.jpg)
[Select] resource realization information, news, we media, blog applet (can be drained, open traffic master, with PC background management)

嵌入式开发:5个可能不再被禁止的C特征
随机推荐
Wechat applet reports an error: typeerror: cannot read property 'SetData' of undefined
With the development of industrial Internet, the landing and application of the Internet has become wider
STM32 porting the fish component of RT thread Standard Edition
This article explains the concepts of typed array, arraybuffer, typedarray, DataView, etc
60 divine vs Code plug-ins!!
随着产业互联网的发展,有关互联网的落地和应用也就变得宽阔了起来
SQL编程问题,测试用例不通过
mysql拒绝访问、管理员身份打开的
Simple understanding of the difference between get request and post submission
rxjs Observable 两大类操作符简介
SQL考勤统计月报表
visualstudio 和sql
【系统分析师之路】第五章 复盘软件工程(敏捷开发)
60 个神级 VS Code 插件!!
Inexplicable error occurred in unity's frequent switching branch result model
JMeter learning notes
【系统分析师之路】第五章 复盘软件工程(软件过程改进)
今日睡眠质量记录80分
香港回归20余年,图扑数字孪生港珠澳大桥,超震撼
Knowledge dissemination cannot replace professional learning!