With the prevalence of Restful architecture in recent years, front-end and back-end separation has become popular, and template rendering has been shifted from the back-end to the front-end, where the back-end only needs to provide resource data, resulting in traditional server-side template scripting languages like JSP and PHP being almost unused. However, in Go, template rendering is not limited to server-side markup languages (e.g. HTML), but GO often uses templating languages to handle, for example, text transformations that insert specific data. While not as flexible as regular expressions, rendering is far more efficient and simpler to use than regular expressions. It is very friendly for certain cloud computing scenarios. Today, we will talk about the technical details of Go language template rendering in detail.
Mechanism of operation
The rendering technique for templates is essentially the same, in one sentence it is a combination of string templates and structured data, in more detail it is the application of a defined template to structured data, using annotation syntax to reference elements in the data structure (e.g. specific fields in Struct, keys in Map) and display their values. The template traverses the data structure during execution and sets the current cursor (`. `` often indicates the current scope) to identify the element at the current position.
Similar to template engines such as jinja in Python and jade in NodeJS, the Go language template engine operates on a similar mechanism.
- create template objects
- parse the template string
- load data to render the template
Go Template Rendering Core Package
The Go language provides two standard libraries to handle template rendering text/template
and html/template
, which have almost identical interfaces but handle different template data. One of them, text/template
, is used to handle template rendering of plain text, while html/template
is specifically used to render formatted HTML strings.
In the following example we use text/template
to handle the rendering of normal text templates.
|
|
Line 4 of the above code introduces text/template
to handle normal text template rendering, line 14 defines a template object test
to parse the variable "The name for student {{.ID}} is {{.Name}}"
template string, and line 16 uses the defined structured data to render the template to the standard output.
Note: The template data to be referenced must be exported, meaning that the corresponding fields must start with an uppercase letter, such as the
ID
andName
fields in theStudent
structure in the example.
Let’s look at another example of HTML string template rendering.
|
|
Note: It is not preferred to use single quotes for strings in Go; use double quotes or backquotes as needed. In addition, the Go language’s string types are inherently different from those of other languages; the
String
in Java,std::string
in C++, andstr
in python3 are all just fixed-width character sequences, while the Go language’s string is a UTF-8 encoded sequence of variable-width characters, meaning that each character is represented by one or more bytes. string is a UTF-8 encoded sequence of variable-width characters, meaning that each character is represented by one or more bytes. String literals in Go are created using double quotes or backquotes ("`").
- double quotes are used to create parsable string literals (escaping is supported, but they cannot be used to reference multiple lines).
- backquotes are used to create native (raw) string literals, which may consist of multiple lines (no escape sequences are supported); native string literals are mostly used for writing multi-line messages, HTML, and regular expressions.
Local deployment execution.
|
|
Go can not only parse template strings directly, but also use ParseFile to parse template files, or the standard processing flow: Create - Load - Render .
Template naming
The previous example template objects are named, either by displaying the naming when creating the template object, or by having the Go template named automatically. But how do you name a template when nested templates are involved, in which case there are multiple template files!
The Go template rendering package provides the ExecuteTemplate() method for rendering Go templates that execute the specified name. For example, when loading the hello
template, you can specify layout.html
.
|
|
In the template string, the action define
is used to define two named templates stu_info
and stu_name
. In this case, although the template object returned by the Parse()
method contains both template names, the template executed by ExecuteTemplate()
is still stu_info
.
Not only can you define a template with define
, but you can also introduce a defined template with template
, similar to jinja’s include
directive.
|
|
In the above example we have introduced the stu_name
template in the stu_info
template using template
and passed the data for the current scope of the stu_name
template (.
), the third parameter is optional, if it is empty, it means that the data passed to the nested template is nil
.
In a nutshell, the template object is created and multiple template files are loaded, the base template (stu_info
) is specified when the template file is executed, and other named templates can be introduced in the base template. The keywords in double brackets such as define
and template
here are actually Go language template directives.
Template directive
From the previous introduction, we know that a template is actually a text or file that contains one or more {{ }}
template strings enclosed by double brackets. Most template strings are simply printed at literal value, but if the template string contains an instruction (Action) it will trigger other behavior. Each directive contains an expression written in the template language. A directive is short but can output complex print values, and the template language includes many features such as control flow if-else
statements and range
loops by selecting structure members, calling functions or methods, expressions, and other instantiation templates.
In summary, Go language template rendering instructions are used to dynamically execute some form of logic and display data, and are broadly classified into the following categories.
- conditional statements
- iterations
- wrapping
- references
We saw the use of define
and template
in the previous example, here’s a look at how the other template directives are used.
Conditional judgments
The syntax of conditional judgments is simple.
|
|
Take a simple example.
|
|
Iteration
For some serially tired data structures, such as Slice and Map, you can use the iterate instruction to iterate through the individual values, similar to iteration in Go itself, using range
for processing.
Detailed specifications are as follows.
|
|
When the object of range
is empty, then the logic specified in the else
branch is executed.
with wrapping
The with
language opens up a contextual environment in Python. For the Go template, the with
statement is similar in that it means that it creates a closed scope within which you can use .
to get the arguments specified by the with
directive, independent of the scope outside, and only with respect to the arguments of with
.
Detailed specifications are as follows.
|
|
As an example.
Inside the with
instruction above, the .
represents the newly opened scope, not the scope outside the with
directive. The .
in the with
instruction and the .
outside it are two unrelated objects. The with
instruction can also have else
, where the .
is the same as the .
is the same as ...
outside of with
; after all, only the with
instruction has a closed context.
Nested templates
|
|
Parameters and pipes
We mentioned earlier that the template
and include
template directives can have an optional third argument to pass data to the inner nested template. Among other things, the template argument can be a basic data type in Go, such as a number, a boolean, a string, an array slice, or a structure. Setting variables in a template can be done using: $variable := value
.
Another feature of the Go language is the pipeline function for templates. Developers familiar with django and jinja should be familiar with this technique, which enables some simple formatting of templates by defining function filters, and through the pipeline philosophy, such processing can be linked together.
|
|
Functions
Since pipelining can be a filter in a template, Go template rendering supports custom functions to extend the functionality of the template, in addition to the built-in functions.
Defining a function in Go template rendering is a two-step process.
- create a map of type
FuncMap
, where key is the name of the template function and value is the definition of its function - inject
FuncMap
into the template
You can use a pipeline syntax like {{ . | fd }}
, but it is also possible to use the normal function call form {{ fd . }}
can also serve the same purpose.
Summary
This note explores the basic syntax of Go template technology through examples, including the three steps of template rendering: Create - Load - Render, and how to use the common template tag directive in Go templates to implement complex data presentation logic. To summarize, Go language templating is an annotation syntax that references elements in a data structure and applies them to a defined template. go templating is often used to handle things like text transformations that insert specific data, and while it is not as flexible as regular expressions, it is faster to render than regular expressions and easier to use.