SoFunction
Updated on 2025-03-01

Detailed explanation of the common basic syntax of golang templates (template)

template

When writing dynamic pages on the website, we often propose the unchanged part as a template. The variable part generates dynamic web pages through the rendering of the backend program. Golang provides the html/template package to support template rendering.

This article does not discuss the template reading and rendering methods of golang backend, but only discusses some basic uses such as embedding variables, rendering variables, and looping in the template.

variable

When golang renders template, it can accept a variable of type interface{}. We can read the value in the variable in the template file and render it into the template.

There are two commonly used types of incoming parameters. One is struct, and the content of the struct field can be read in the template for rendering. There is also a map[string]interface{}, which can be rendered using key in the template.

I usually use the second one, and the efficiency may be a little worse, but it is convenient to use.

All syntax support embedded in the template needs to be marked with {{}}.

In the template file, . represents the current variable, that is, in the non-circular body, . represents the variable passed in. Suppose we define a structure:

type Article struct {
  ArticleId int
  ArticleContent string
}

Then we can pass it in the template

<p>{{.ArticleContent}}<span>{{.ArticleId}}</span></p>

to obtain and render the content of the variable into the template. Assuming that the content of the above structure is ArticleId:1 ArticleContent: "hello", the corresponding rendered template content is:

<p>hello<span>1</span></p>

Isn't it very simple?

Of course, we sometimes need to define variables, for example, we need to define an article variable and initialize it to "hello", so we can write this way:

{{$article := "hello"}}

Suppose we want to assign the content of the passed value to the article, we can write it like this:

{{$article := .ArticleContent}}

In this way, we can get the content of this variable by using {{$article}}.

function

Golang's templates are actually very limited in functions. Many complex logics cannot be expressed directly using template syntax, so they can only be bypassed by template functions.

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

The function set is defined as:

type FuncMap map[string]interface{}

The key is the name of the method, and the value is the function. There is no limit on the number of parameters in this 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 type error. The difference between these two functions is that when the second function is called in the template, assuming that 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.

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

{{funcname .arg1 .arg2}}

Suppose we define a function

func add(left int, right int) int

Then, in the template file, call it

{{add 1 2}}

You can get it

3

As a result, golang's predefined function does not have add, so it is a bit troublesome.

judge

golang's template also supports if conditional judgment, currently supports the simplest judgment of bool type and string type

{{if .condition}}
{{end}}

When .condition is of type bool, true means execution, and when .condition is of type string, non-empty means execution.

Of course, it also supports else, else if nesting

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

Suppose we need logical judgments, such as when we judge whether or not or size is not equal to or, we need some built-in template functions to do these tasks. Some of the commonly used built-in template functions are:

  • Not non

{{if not .condition}}
{{end}}

  • and

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

  • or

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

  • eq equals

{{if eq .var1 .var2}}
{{end}}

  • ne does not equal

{{if ne .var1 .var2}}
{{end}}

  • lt less than (less than)

{{if lt .var1 .var2}}
{{end}}

  • le is 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}}

cycle

golang's template supports range loops to traverse the contents in map and slice, and the syntax is:

{{range $i, $v := .slice}}
{{end}}

In this range loop, we can access the traversal value through iiv, and there is another traversal method:

{{range .slice}}
{{end}}

This method cannot access the index or key value, and you need to access the corresponding value through .

{{range .slice}}
{{.field}}
{{end}}

Of course, here is used. to access the traversal value, so what should we do if we want to access external variables in it? (such as the variable passed in the rendering template), here we need to use $. to access external variables

{{range .slice}}
{{$.ArticleContent}}
{{end}}

Nesting of templates

When writing templates, we often integrate common templates. For example, each page has a navigation bar and a footer. We often write it into a separate module to import all pages so that there is no need to write it repeatedly.

Any web page has a main template, and we can then embed sub-templates in the main template to implement module sharing.

When a template wants to introduce a sub-template, we use the following statement:

{{template "navbar"}}

In this way, we will try to load a sub-template with the name navbar, and we also have to define a sub-template to implement the "navbar" sub-template.

The definition of a sub-template is:

{{define "navbar"}}
{{end}}

Content between definitions will override {{template "navbar"}}

Of course, the child template is separated, so can the child template obtain the variables of the parent template? Of course, we just need to use

{{template "navbar" .}}

You can pass the current variable to the sub-template, which is also quite convenient.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.