This is a creation in Article, where the information may have evolved or changed.
The Go official library offers two template libraries : Text/template and html/template. The two libraries are similar, except html/template that the HTML format has been specially processed, which needs to be used html/template when outputting HTML-formatted code.
Using templates can help us write some common code, or provide a clear file layout, or provide a code generator.
official documentation provides a good way to use templates, where text/template provides a way to use the underlying template, such as Action, Argument, Pipeline, Variable, Function, template nesting introduction, html/template describes the Context. This article assumes that you already understand these basics. If you are not sure, or have not used the template, you can refer to the reference document at the end of the study.
text/template Although the official documentation on template nesting is simple to introduce, but for the use of nested templates for the actual development, as well as considerations are not described in detail, so this article focuses on the use of nested templates.
Although this article is named as a best practice for nested templates, it's just one of the best practices, to be precise. If the reader has other practical scenarios, or better deal with the template nesting scenarios, welcome to discuss.
When we develop a Web application, it is unavoidable to use the template.
Generally a site contains a lot of pages, such as news pages, registration pages, the list of articles and so on. Different news may use the same news layout template, different article detail page may also use the same article layout page, while the News layout template and Article layout page may also have some common things, such as header, footer, navigation bar and so on. How to extract these common things into a unified template?
This article will step through these techniques and first describe the use of nested files.
Parse vs Parsefiles vs Parseblob
Let's start by looking at how the three files are different. In fact, there are five of files:
funcparsefiles (Filenames ... string) ( *template , error) Funcparseglob (patternstring) (*template , error) func (t * Template ) Parse (textstring) (*template , error) func (t span class= "variable" style= "color: #08080" >*template ) parsefiles (Filenames ... string) (*template , error) func (t *template ) Parseglob (patternstring) (*template , error)
Parse used to parse a string that represents the content of the template, and the nested template is associated with the template.
Tmpl, err: = template. New ("name"). Parse (...) //Error checking elidederr = Tmpl. Execute (out, data)
And
Import "Html/template" ... t, err: = template. New ("foo"). Parse (' \{\{define ' t "\}\}hello, \{\{.\}\}!\{\{end\}\} ') Err = T.executetemplate (out," T ","<script >alert (' You have been Pwned ')</script>")
ParseFiles used to parse a named set of file templates, when the template is defined in different files, using this method can produce an executable template, the template will be executed without error.
parseglob and parsefiles similar, it uses filepath. Glob the pattern matches the way the files are traversed, and the files are generated as templates.
These two functions can also be *Template used as methods. When used as a function, it returns the name of the template as the name of the first file, the template with the first file as the base template.
At the same time, the subsequent files will also generate templates as the template of the association, you can find it through Lookup the method, because each template is saved its associated version:
Set Map [string]*template
Let's illustrate the use of nested templates with an example.
There are two files under the current folder.
Header.html
is "Footer"\}\}
Footer.html
"Footer" is \{\{. Body\}\}\{\{end\}\}
Test procedure:
Packagemainimport ("FMT" "Html/template" "Net/http") funchandler (w http. Responsewriter, R *http. Request) {T, _: = template. Parsefiles ( "header.html" , "footer.html" ) ERR: = T.execute (W, Map[string]string{ "title" : "My title" , : "Hi this is My Body "}" Iferr!=nil{panic (Err)}}funcmain () {http. Handlefunc ( "/" , handler ) http. Listenandserve (, nil)}
Browser access http://localhost:8080/ will result in rendering:
is is
You can see that the results are basically in line with expectations. header.html Nested the footer Templates, rendering time to header.html Display for the main template, nested rendering footer.html 。
But the above results show a little bit of a problem, that is footer rendering does not show the result of body, because data is passed to the main template, Nested templates If you want to use this data, you need to pass it to it in a nested place. We can modify header.html :
<divclass=""></div>\}\}
footer.html This allows you to render using the incoming data:
Title Ismy titlebody Ishithisismybody
When using ParseFiles 、 ParseGlob function , the default is to use the last part of the file's path as the template name, such as a file a/foo The template name is called foo , but if the parameters in different folders have the same file name, the last template file with the same name will "overwrite" the template of the previous duplicate file, the implementation of the official library cannot save the duplicate template file.
Execute vs Executetemplate
The example above shows the use of a simple nested template, but if we exchange the order of two files, as follows:
template. Parsefiles ("footer.html","header.html"map[string]string{" Title ":" "My title","Body":"Hi This is My Body"}) Iferr!=nil{panic (Err)}}
After running the browser access, you will find no error, but also did not render anything.