Standard library template in golang

The html/template package implements a data-driven template for generating secure HTML output against code injection. It provides the same interface as the text/template package. The text/template package should be used in all scenarios where html is output in the Go language.

Template

In MVC based Web architecture, we usually need to render some data to HTML files at the back end to achieve dynamic Web page effect

Template example

The output is obtained by applying the template to a data structure (that is, the data structure is used as a parameter of the template). The comments in the template refer to the elements of the data interface (generally such as the fields of the structure or the keys of the dictionary) to control the execution process and obtain the values to be rendered. When the template is executed, it will traverse the structure and represent the pointer as'. '(called "dot") to the value of the current position of the data structure during operation.

The input text used as a template must be utf-8 encoded text. " "Action" - data operation and control unit - defined by ""; all text outside the action is copied to the output without modification. There can be no line breaks inside the action, but comments can have line breaks.

The HTML file code is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home page</title>
</head>
<body>
    <p>Hello {{.}}</p>
</body>
</html>

Our HTTP server code is as follows:

func main() {
	http.HandleFunc("/", SayHello)
	err := http.ListenAndServe(":8000", nil)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
}
func SayHello(w http.ResponseWriter, r *http.Request) {
	// Parse the specified file and generate the template object
	tmpl, err := template.ParseFiles("./templates/index.html")
	if err != nil {
		fmt.Println("create template failed, err: ", err)
		return
	}
	// Render the template with the given data and write the results to w
	tmpl.Execute(w, "sankuan")
}

Template syntax

{{.}}
The template syntax is contained between {{and}}, where the point in {{.}} represents the current object.
When we pass in a structure object, we can access the corresponding fields of the structure according to. For example:

func main() {
	http.HandleFunc("/", SayHello)
	if err := http.ListenAndServe(":8000", nil); err != nil {
		fmt.Println(err.Error())
		return
	}
}
func SayHello(w http.ResponseWriter, r *http.Request) {
	// Parse the template file and generate the template object
	tmpl, err := template.ParseFiles("./templates/index.html")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	// Render the data to the template and write it to w
	user := User{"Zhang San", 18, true}
	tmpl.Execute(w, &user)
}
type User struct {
	Name string
	Age uint8
	Gender bool
}

The HTML file code is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home page</title>
</head>
<body>
    <p>Name: {{.Name}}</p>
    <p>Age: {{.Age}}</p>
    <p>Gender: {{.Gender}}</p>
</body>
</html>

Similarly, when the variable we pass in is map, we can also get the value in the template file through. According to the key.

notes

<p>Gender: {{/*.Gender*/}}</p>
Comments are ignored during execution. Multiple lines are allowed. Comments cannot be nested and must start and end close to the delimiter.

pipeline

Pipeline refers to the operations that generate data, such as {}}, {{. Name}}. The template syntax of Go supports the use of pipeline symbol | to link multiple commands, which is similar to the pipeline under unix: | the previous command will pass the operation result (or return value) to the last position of the latter command.
Note: pipeline is not only used. In the template syntax of Go, the concept of pipeline is to transfer data. As long as data can be generated, it is pipeline.

Define variables in html

In Action, you can initialize a variable to capture the execution result of the pipeline. The initialization syntax is as follows:

<body>
    <p>Name: {{.Name}}</p>
    <p>Age: {{.Age}}</p>
    <p>Gender: {{.Gender}}</p>  {{$score := 88}}
    <p>fraction: {{$score}}</p>
</body>

if judgment

{{if Lt. age 18}} minor {{else}} adult {{end}}

The template of golang also supports conditional judgment of if. Currently, it supports the simplest judgment of bool type and string type

{{if .condition}} {{end}}
When the. condition is of bool type, it is true for execution; when the. condition is of string type, it is not empty for execution.

Of course, else, else if nesting is also supported

{{if .condition1}} {{else if .contition2}} {{end}}

Suppose that we need logical judgment, such as and or, size not equal to and so on, we need some built-in template functions to do these work. At present, some commonly used built-in template functions are:

not non

{{if not .condition}}
{{end}}
And and

{{if and .condition1 .condition2}}
{{end}}
Or or

{{if or .condition1 .condition2}}
{{end}}
eq equals

{{if eq .var1 .var2}}
{{end}}
ne is not equal to

{{if ne .var1 .var2}}
{{end}}
lt less than

{{if lt .var1 .var2}}
{{end}}
le less than or equal to

{{if le .var1 .var2}}
{{end}}
gt greater than

{{if gt .var1 .var2}}
{{end}}
ge is greater than or equal to

{{if ge .var1 .var2}}
{{end}}

loop

main.go

func main() {
	http.HandleFunc("/", SayHello)
	if err := http.ListenAndServe(":8000", nil); err != nil {
		fmt.Println(err.Error())
		return
	}
}
func SayHello(w http.ResponseWriter, r *http.Request) {
	// Parse the template file and generate the template object
	tmpl, err := template.ParseFiles("./templates/index.html")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	// Render the data to the template and write it to w
	user := User{"ha-ha", 88, false, []int{11, 22, 33}, map[string]interface{}{
		"name": "Timed transmission is open",
		"age": 998,
	}}
	tmpl.Execute(w, &user)
}
type User struct {
	Name string
	Age uint8
	Gender bool
	Score []int
	Height map[string]interface{}
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home page</title>
</head>
<body>
{{ .Name }}
{{ .Score }}

{{range .Score}}
{{.}}
{{end}}
{{range $i, $v := .Score}}
{{$i}}---{{$v}}
{{end}}

{{range .Height}}
{{.}}
{{end}}
{{range $k, $v := .Height}}
{{$k}}---{{$v}}
{{end}}
</body>
</html>

Nesting of templates

When writing templates, we often integrate common templates. For example, each page has a navigation bar and footer. We often write them as a separate module to import all pages, so that there is no need to write them repeatedly.
Any web page has a main template, and then we can embed sub templates in the main template to realize module sharing.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home page</title>
</head>
<body>

<!--Define sub templates-->
{{define "navbar"}}
<h1>Ah ha ha ha</h1>
<p>hey</p>
{{end}}

<!--Use sub template-->
{{template "navbar" .}}

</body>
</html>

Functions used in templates

In fact, the template function of golang is very limited. Many complex logic cannot be expressed directly by template syntax, so we can only use template functions to bypass it.

First, when the template package creates a new template, it supports the. Funcs method to import custom function sets into the template. Subsequent files rendered through the template support direct calls to these functions.

The function set is defined as:

type FuncMap map[string]interface{}

key is the name of the method, and value is the function. There is no limit on the number of parameters of the function, but there is a limit on the return value. There are two options, one is to have only one return value, and the other is to have two return values, but the second return value must be of error type. The difference between the two functions is that when the second function is called in the template, it is assumed that the template function If the return of the second parameter of the number is not empty, the rendering step will be interrupted and an error will be reported.

In the template file, calling the method is also very simple:

{{funcname .arg1 .arg2}}

Suppose we define a function

func add(left int, right int) int

In the template file, call

{{add 1 2}}

You can get the value: 3

As a result, the predefined function of golang does not have add, so it is a little troublesome.

main.py

func main() {
	http.HandleFunc("/", SayHello)
	if err := http.ListenAndServe(":8000", nil); err != nil {
		fmt.Println(err.Error())
		return
	}
}
func SayHello(w http.ResponseWriter, r *http.Request) {
	// Parse the template file and generate the template object
	tmpl := template.New("./templates/index.html")
	tmpl.Funcs(template.FuncMap{
		"add": Add,
	})
	tmpl, err := tmpl.ParseFiles("./templates/index.html")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	// Render the data to the template and write it to w
	user := User{"ha-ha", 88, false, []int{11, 22, 33}, map[string]interface{}{
		"name": "Timed transmission is open",
		"age": 998,
	}}
	if err := tmpl.ExecuteTemplate(w, "index.html", user); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

	//tmpl.Execute(w, &user)
}
type User struct {
	Name string
	Age uint8
	Gender bool
	Score []int
	Height map[string]interface{}
}
func Add(a, b int) int {
	return a + b
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home page</title>
</head>
<body>

Ha ha ha ha

{{add 11 22}}

</body>
</html>

Predefined function

When executing a template, functions are searched from two function Dictionaries: the first is the template function dictionary, and the second is the global function dictionary. Generally, functions are not defined in the template, but added to the template using the Funcs method.

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 will be executed;
or
    Returns the first non empty Parameter or the last parameter;
    or"or x y"Equivalent to"if x then x else y";All parameters will be 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 indexed/The value pointed to by the key;
    as"index x 1 2 3"return x[1][2][3]Each indexed body must be an array, slice, or dictionary.
print
    Namely fmt.Sprint
printf
    Namely fmt.Sprintf
println
    Namely fmt.Sprintln
html
    Returns the text representation of its parameter HTML Escape code equivalent representation.
urlquery
    Returns the embeddable text representation of its parameter URL The escape code equivalent representation of the query.
js
    Returns the text representation of its parameter JavaScript Escape code equivalent representation.
call
    The execution result is the return value of the first parameter called. The parameter must be a function type, and the other parameters are used as parameters for calling the function;
    as"call .X.Y 1 2"Equivalent to go In language dot.X.Y(1, 2);
    among Y Is the value of a function type field or dictionary, or other similar situations;
    call The execution result of the first parameter of must be the value of the function type (and predefined functions such as print Significantly different);
    The function type value must have 1 to 2 return values. If there are 2, the latter must be error Interface type;
    If there are 2 methods that return values error wrong nil,The template execution will be interrupted and returned to the invoking template executor;

Comparison function

Boolean functions treat any type of zero as false and the rest as true.

The following is a collection of binary comparison operations defined as functions:

    eq      If arg1 == arg2 Returns true
    ne      If arg1 != arg2 Returns true
    lt      If arg1 < arg2 Returns true
    le      If arg1 <= arg2 Returns true
    gt      If arg1 > arg2 Returns true
    ge      If arg1 >= arg2 Returns true

In order to simplify multi parameter equality detection, eq (only eq) can accept 2 or more parameters. It will compare the first parameter with other parameters in turn and return the results of the following formula:

{{eq arg1 arg2 arg3}}

The comparison function is only applicable to basic types (or redefined basic types, such as "type Celsius float32"). However, integers and floating-point numbers cannot be compared with each other.

Posted on Wed, 01 Dec 2021 23:28:45 -0500 by jtgraphic