This is the 28th day of my participation in the August Text Challenge.More challenges in August
The content of this article comes from my study of Go Web programming practical school and summary of my practice
Template engines
Text/Template, a common template engine library in the Go language, is used to process text in any format. In addition, the Go language provides a separate HTML/Template package for generating secure HTML documents that are resistant to code injection
Principle of the template
Templates and template engines
In the Web architecture given to the MVC model, we often present the invariable parts as templates, and those mutable parts are provided with data by back-end applications rendered by the template engine to generate dynamic Web pages
A template can be understood as a predefined HTML document. Template rendering can be thought of simply as a text substitution operation — the back end replaces the markup in the HTML document with the corresponding data
Templates were created to separate the display from the data (i.e., the front and back ends); Templating techniques vary, but the essence is to run template files and data through a templating engine to produce the final HTML document. There are many template engines, such as Node.js EJS, Nunjucks, and so on
Template engine for the Go language
Go language built-in text template engine text/ Template package, and HTML/Template package for generating HTML documents, they are basically similar to the use of the following points:
- Template files usually have the suffix
.tmpl
and.tpl
(Other suffixes can also be used), must be usedUTF-8
coding - Used in template files
{{}}
To wrap and represent the data that needs to be passed in - Data passed to the template can be passed through dots
.
To access. If the data matches the type, you can pass{{.FieldName}}
To access its fields - Out of the
{{}}
Outside the package, other contents are not processed, the original output
The use of the Go language template engine is divided into defining template files, parsing template files and rendering files
-
Defining template files
To define a template file is to define a template file according to the corresponding syntax rules
-
Parsing a template file
The HTML/Template package provides the following methods to parse template files and get template objects; The New() function creates a template object and gives it a template name. The New() function is defined as follows:
func New(name string) *Template Copy the code
You can use the Parse() function to create template objects and complete parsing of template content. Parse() defines the following method:
func (t *Template) Parse(src string) (*Template, err) Copy the code
If you want to parse a template file, you can use the ParseFile() function, which returns a template object. This function is defined as follows:
func ParseFiles(filenames ...string) (*Template, error) Copy the code
If you want to parse files in batches, you can use the ParseGlob() function. This function is defined as follows:
func ParseGlob(pattern string) (*Template, error) Copy the code
You can use the ParseGlob() function for regular matching, such as template.parseglob (“a*”) if you have a template file starting with a in the current parse directory.
-
Render template file
The HTML /template package provides the Execute() and ExecteTemplate() methods to render templates
func (t *template) Execute(wr Writer, data interface{}) error {} func (t *template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {} Copy the code
A template name is added to the template object when the New() function is created, and the ‘Execute() method looks for that name by default for data fusion
The ParseFile() function allows multiple templates to be loaded at once. Instead of using Execute() to perform data fusion, you can use the ExecuteTemplate() method to specify the template name to perform data fusion
Using HTML/template package
Create a template
In the Go language, you can execute and output HTML documents by applying a template to a data structure, that is, by taking that data structure as an argument to the template
The template traverses the data structure as it executes, pointing a pointer to the running data structure. The current position of
The input text used as a template must be UTF-8 encoded text; Action is the data operation and control unit, Action is defined by {{and}}; All text outside the Action is copied to the output unchanged. Actions cannot have line breaks inside, but comments can have line breaks
Now create and practice templates
-
Example to create a new project, then respectively in the example of creating examp/template/index TMPL and main. Go
-
Creating a template File
// example/template/index.tmpl <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta Name ="viewport" content="width=device-width, initial-scale=1.0"> <title> template </title> </head> <body> {{.}}</p> </body> </html>Copy the code
-
Create a file for creating and rendering templates (main.go)
package main import ( "fmt" "html/template" "net/http" ) func helloHandleFunc(w http.ResponseWriter, r *http.Request) { // Parse the template tpl, err := template.ParseFiles("./template/index.tmpl") iferr ! =nil { fmt.Println("template parsefile failed, err:", err) return } // Render template name := "learn Go" tpl.Execute(w, name) } func main(a) { http.HandleFunc("/", helloHandleFunc) http.ListenAndServe(": 8082".nil)}Copy the code
-
Enter the startup command at the command line terminal (note that it must be in the file path)
go run main.go Copy the code
-
Visit http://localhost:8082/ in your browser and the final effect is as follows:
Go language template syntax
Template syntax is contained between {{and}}, where. Represents the current object, which, when passed a structure object, can be based on. To access the corresponding fields of the structure, for example to write a template rendering of personal information:
// example/template/user.tpml<! DOCTYPE html> <html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="Width = device - width, initial - scale = 1.0"/> <title> Template </title> </head> <body> <table border="1">
<thead>
<th rowspan="2"Personal information > < / th > < thead > < tr > < td > nickname < / td > < td > {{. Nickname}} < / td > < / tr > < tr > < td > age < / td > < td > {{. Age}} < / td > < / tr > < tr > <td>gender</td> <td>{{.Gender}}</td> </tr> <tr> <td>email</td> <td>{{.Email}}</td> </tr> </table> </body> </html>Copy the code
Complete the parse template files and data
// example/main.go
type User struct {
Nickname string
Gender string
Age int
Email string
}
func handleSayHi(w http.ResponseWriter, r *http.Request){
// Parse the template
tpl, err := template.ParseFiles("./template/user.tmpl")
iferr ! =nil {
fmt.Println("create template failed, err:", err)
return
}
// Render the template with the given data and write the result to w
user := User{
Nickname: "Forest",
Gender: "man",
Age: 22,
Email: "[email protected]",
}
tpl.Execute(w, user)
}
Copy the code
Run to start the program, and then in the browser visit: http://localhost:8082/say-hi, rendering is as follows:
Map can also be passed in a template file when passing in variables. To access the value
Common template syntax
-
annotation
In Go, an HTML template has the following comment structure:
{{/* This is a comment and will not be parsed */}} Copy the code
-
Pipe (pipeline)
Pipes are operations that generate data; . Such as: {{}}, {{. Nickname}}, pipeline operators Go template syntax support | to link multiple commands, usage and UNIX pipelines under similar: | the previous command will stun results (or return values) is passed to a command after the last position
: : : tip
Not only use | is pipeline, in the template syntax, the concept of the pipeline when passing data, as long as can produce the structure of the data, is the pipeline
: : :
-
variable
You can initialize a variable in the Action to capture the pipe’s execution result. The initialization syntax is as follows:
$variable := pipline Copy the code
$variable is the name of the variable. Declaring an Action variable produces no output
-
conditional
There are several conditions in the Go template syntax:
{{if pipline}} T1 {{end}} {{if pipline}} T1 {{else}} T0 {{end}} {{if pipline}} T1 {{else if pipline}} T0 {{end}} Copy the code
-
Renge keyword
In the template syntax of Go, the range keyword is used for traversal, where the value of pipline must be array, slice, map, or channel. The syntax begins with {{range pipline}} and ends with {{end}} in the following form:
{{range pipline}} T1 {{end}} Copy the code
If the pipline value has a length of 0, there is no output. {{else}} can also be in the middle, as follows:
{{range pipline}} T1 {{else}} T0 {{end}} Copy the code
If the pipline value has a length of 0, T0 is executed
The following is an example:
package main import ( "html/template" "log" "net/http" ) func handleRange(w http.ResponseWriter, r *http.Request) { rangeTemplate := `
{{if .Kind}}
{{range $i, $v := .MapContent}}
{{$i}} => {{$v}},{{$.OutsideContent}}
{{end}}
{{else}}
{{range .MapContent}}
{{.}}, {{$.OutsideContent}}
{{end}}
{{end}}
` str1 := []string{"first range"."use index and value"} str2 := []string{"second range"."not use index and value"} type Content struct { MapContent []string OutsideContent string Kind bool } var content = []Content{ {str1, "The first time out.".true}, {str2, "The second time out.".false}},// Create a template and parse the characters in it t := template.Must(template.New("range").Parse(rangeTemplate)) fmt.Println("t:", t) for _, c := range content { err := t.Execute(w, c) iferr ! =nil { log.Println("executing template:", err) } } } func main(a) { http.HandleFunc("/range", handleRange) http.ListenAndServe(": 8082".nil)}Copy the codeAfter re-running the program, the browser will look like this:
-
With the keyword
In the template syntax of Go, the with keyword is somewhat similar to the if keyword in that the {{with}} operation conditionally executes its body when the passed pipe part is empty. As follows:
{{with pipline}} T1 {end} Copy the code
If the pipline is empty, no output is generated. {{else}}; Such as:
{{with pipline}} T1 {{else}} T0 {{end}} Copy the code
If the pipline is empty, it does not change. And execute T0. Otherwise set. To the value of pipline and execute T1
-
The comparison function
Boolean functions treat any type of zero value as false and the rest as true. For example, the following commonly used binary comparison operator:
The operator instructions eq Equality judgment; Example: arg1 == arg2 ne Unequal judgment; For example: arg1! = arg2 lt Less than judgment; For example, arg1 < arg2 le Less than or equal judgment; Example: arg1 <= arg2 gt Greater than judgment; For example, arg1 > arg2 ge Greater than or equal to judgment; Example: arg1 >= arg2 In order to simplify multi-parameter equality detection, EQ can accept 2 or more parameters and compare the first parameter with the rest parameters as follows:
{{eq arg1 arg2 arg3 ... argn}} Copy the code
That is, only the following comparison can be made
arg1 ==arg2 || arg1 == arg2 || ... || arg1 == argn Copy the code
Comparison functions apply only to primitive types (or redefined primitive types, such as “Type Balance Float32”). But integers and floating-point numbers cannot be compared
-
Predefined function
Predefined functions are defined in the template library and can be directly used in {{}}. The following table lists the names and functions of predefined functions:
The function name instructions and The function returns either its first empty argument or its last argument: "and x y"
Is equivalent to"if x then y else x"
. All arguments are executedor Returns either the first non-empty argument or the last argument, i.e "or x y"
Is equivalent to"if x then x else y"
. All arguments are executednot Returns a Boolean “No” for its single argument len Returns the integer type length of its argument index The execution result is index()
The first argument after the function is indexed to the remaining argument after the first argument. Each indexed body must be an array, slice, mapprint namely fmt.Sprint
printf namely fmt.Sprintf
println namely fmt.Sprintln
html Returns the HTML escape equivalent representation of the text representation of its arguments urlquery Returns the escape equivalent representation of an embeddable URL query whose parameter text representation js Returns the JavaScript decoded equivalent representation of the text representation of its arguments call The result is the return value of the call’s first argument, which must be of function type, and the remaining arguments as arguments to call the function -
Custom function
Templates in the Go language support custom functions. The custom function is implemented by calling the Funcs() method and is defined as follows:
func (t *Template) Funcs(funcMap FuncMap) *Template Copy the code
The Funcs() method adds key-value pairs from the funcMap parameter to the function dictionary of the template object. If one of the key-value pairs of funcMap has a value that is not a function type, or if the return value does not meet requirements, a panic error is reported, but the members of the function list of the template object can be overridden. Method returns a template object for the chain call. FuncMap is defined as follows:
type FuncMap map[string]interface{} Copy the code
The FuncMap type defines a mapping of function name strings to functions, and each function must have one or two return values. If there are two return values, the latter must be of error interface type; If a method with 2 returns values returns error non-nil, template execution breaks and returns the error to the caller
When a template is executed, functions are looked up from two function dictionaries: first, the template function dictionary, and then the global function dictionary. Instead of defining functions in templates, we use the Funcs() method to add functions to templates.