Merge commit '716a30fead9579d5ec6340a5567b7c72c52bbdd2' into ja

This commit is contained in:
Shin Kojima
2014-12-17 01:06:14 +09:00

View File

@@ -1,19 +1,19 @@
# 7.4 Templates
## What is template?
## What is a template?
I believe you've heard MVC design model, where Model processes data, View shows results, Controller handles user requests. As for View level. Many dynamic languages generate data by writing code in static HTML files, like JSP implements by inserting `<%=....=%>`, PHP implements by inserting `<?php.....?>`.
Hopefully you're aware of the MVC (Model, View, Controller) design model, where models process data, views show the results and finally, controllers handle user requests. For views, many dynamic languages generate data by writing code in static HTML files. For instance, JSP is implemented by inserting `<%=....=%>`, PHP by inserting `<?php.....?>`, etc.
The following shows template mechanism:
The following demonstrates the template mechanism:
![](images/7.4.template.png?raw=true)
Figure 7.1 Template mechanism
Most of content that web applications response to clients is static, and dynamic part is usually small. For example, you need to show a list of visited users, only user name is dynamic, and style of list is always the same, so template is for reusing static content.
Most of the content that web applications respond to clients with is static, and the dynamic parts are usually very small. For example, if you need to show a list users who have visited a page, only the user name would be dynamic. The style of the list remains the same. As you can see, templates are useful for reusing static content.
## Template in Go
## Templating in Go
In Go, we have package `template` to handle templates, and use functions like `Parse`, `ParseFile`, `Execute` to load templates from text or files, then execute merge like figure 7.1.
In Go, we have the `template` package to help handle templates. We can use functions like `Parse`, `ParseFile` and `Execute` to load templates from plain text or files, then evaluate the dynamic parts, like in figure 7.1.
Example:
@@ -24,21 +24,21 @@ Example:
t.Execute(w, user) // merge.
}
As you can see, it's very easy to use template in Go, load and render data, just like in other programming languages.
As you can see, it's very easy to use, load and render data in templates in Go, just like in other programming languages.
For convenient purpose, we use following rules in examples:
For the sake of convenience, we will use the following rules in our examples:
- Use `Parse` to replace `ParseFiles` because `Parse` can test content from string, so we don't need extra files.
- Use `Parse` to replace `ParseFiles` because `Parse` can test content directly from strings, so we don't need any extra files.
- Use `main` for every example and do not use `handler`.
- Use `os.Stdout` to replace `http.ResponseWriter` because `os.Stdout` also implemented interface `io.Writer`.
- Use `os.Stdout` to replace `http.ResponseWriter` since `os.Stdout` also implements the `io.Writer` interface.
## Insert data to template
## Inserting data into a template
We showed you how to parse and render templates above, let's take one step more to render data to templates. Every template is an object in Go, so how to insert fields to templates?
We've just showed you how to parse and render templates. Let's take it one step further and render data to our templates. Every template is an object in Go, so how do we insert fields to templates?
### Fields
Every field that is going to be rendered in templates in Go should be put inside of `{{}}`, `{{.}}` is shorthand for current object, it's similar to Java or C++. If you want to access fields of current object, you should use `{{.FieldName}}`. Notice that only exported fields can be accessed in templates. Here is an example:
In Go, Every field that you intend to be rendered within a template should be put inside of `{{}}`. `{{.}}` is shorthand for the current object, which is similar to its Java or C++ counterpart. If you want to access the fields of the current object, you should use `{{.FieldName}}`. Notice that only exported fields can be accessed in templates. Here is an example:
package main
@@ -58,7 +58,7 @@ Every field that is going to be rendered in templates in Go should be put inside
t.Execute(os.Stdout, p)
}
The above example outputs `hello Astaxie` correctly, but if we modify a little bit, the error comes out:
The above example outputs `hello Astaxie` correctly, but if we modify our struct a little bit, the following error emerges:
type Person struct {
UserName string
@@ -67,16 +67,16 @@ The above example outputs `hello Astaxie` correctly, but if we modify a little b
t, _ = t.Parse("hello {{.UserName}}! {{.email}}")
This part of code will not be compiled because we try to access a field that is not exported; however, if we try to use a field that does not exist, Go simply outputs empty string instead of error.
This part of the code will not be compiled because we try to access a field that has not been exported. However, if we try to use a field that does not exist, Go simply outputs an empty string instead of an error.
If you print `{{.}}` in templates, Go outputs formatted string of this object, it calls `fmt` underlying.
If you print `{{.}}` in a template, Go outputs formatted string of this object, calling `fmt` under the covers.
### Nested fields
We know how to output a field now, what if the field is an object, and it also has its fields, how to print them all in loop? We can use `{{with …}}…{{end}}` and `{{range …}}{{end}}` to do this job.
We know how to output a field now. What if the field is an object, and it also has its own fields? How do we print them all in one loop? We can use `{{with …}}…{{end}}` and `{{range …}}{{end}}` for exactly that.
- `{{range}}` just like range in Go.
- `{{with}}` lets you write same object name once, and use `.` as shorthand( ***Similar to `with` in VB*** ).
- `{{with}}` lets you write the same object name once and use `.` as shorthand for it ( ***Similar to `with` in VB*** ).
More examples:
@@ -117,9 +117,9 @@ More examples:
t.Execute(os.Stdout, p)
}
### Condition
### Conditions
If you need to check conditions in templates, you can use syntax `if-else` just like you use it in Go programs. If pipeline is empty, default value of `if` is `false`. Following example shows how to use `if-else` in templates:
If you need to check for conditions in templates, you can use the `if-else` syntax just like you do in regular Go programs. If the pipeline is empty, the default value of `if` is `false`. The following example shows how to use `if-else` in templates:
package main
@@ -142,21 +142,21 @@ If you need to check conditions in templates, you can use syntax `if-else` just
tIfElse.Execute(os.Stdout, nil)
}
As you can see, it's easy to use `if-else` in you tempaltes.
As you can see, it's easy to use `if-else` in templates.
** Attention ** You CANNOT use conditional expression in if, like `.Mail=="astaxie@gmail.com"`, only boolean value is acceptable.
** Attention ** You CANNOT use conditional expressions in if, for instance `.Mail=="astaxie@gmail.com"`. Only boolean values are acceptable.
### pipelines
Unix users should be familiar with `pipe` like `ls | grep "beego"`, this command filter files and only show them that contains `beego`. One thing I like Go template is that it support pipe, anything in `{{}}` can be data of pipelines. The e-mail we used above can cause XSS attack, so how can we fix this through pipe?
Unix users should be familiar with the `pipe` operator, like `ls | grep "beego"`. This command filters files and only shows those that contain the word `beego`. One thing that I like about Go templates is that they support pipes. Anything in `{{}}` can be the data of pipelines. The e-mail we used above can render our application vulnerable to XSS attacks. How can we address this issue using pipes?
{{. | html}}
We can use this way to escape e-mail body to HTML, it's quite same as we write Unix commands and convenient for using template functions.
We can use this method to escape the e-mail body to HTML. It's quite the same as writing a Unix command, and its convenient for use in template functions.
### Template variable
### Template variables
Sometimes we need to use local variables in templates, and we can use them with `with``range``if`, and its scope is between these keywords and `{{end}}`. Declare local variable example:
Sometimes we need to use local variables in templates. We can use them with the `with`, `range` and `if` keywords, and their scope is between these keywords and `{{end}}`. Here's an example of declaring a global variable:
$variable := pipeline
@@ -166,15 +166,15 @@ More examples:
{{with $x := "output"}}{{printf "%q" $x}}{{end}}
{{with $x := "output"}}{{$x | printf "%q"}}{{end}}
### Template function
### Template functions
Go uses package `fmt` to format output in templates, but sometimes we need to do something else. For example, we want to replace `@` with `at` in our e-mail address like `astaxie at beego.me`. At this point, we have to write customized function.
Go uses the `fmt` package to format output in templates, but sometimes we need to do something else. As an example scenario, let's say we want to replace `@` with `at` in our e-mail address, like `astaxie at beego.me`. At this point, we have to write a customized function.
Every template function has unique name and associates with one function in your Go programs as follows:
Every template function has a unique name and is associated with one function in your Go program as follows:
type FuncMap map[string]interface{}
Suppose we have template function `emailDeal` and it associates with `EmailDealWith` in Go programs, then we use following code to register this function:
Suppose we have an `emailDeal` template function associated with its `EmailDealWith` counterpart function in our Go program. We can use the following code to register this function:
t = t.Funcs(template.FuncMap{"emailDeal": EmailDealWith})
@@ -262,7 +262,7 @@ Here is a list of built-in template functions:
## Must
In package template has a function `Must` which is for checking template validation, like matching of braces, comments, variables. Let's give an example of `Must`:
The template package has a function called `Must` which is for validating templates, like the matching of braces, comments, and variables. Let's take a look at an example of `Must`:
package main
@@ -293,15 +293,15 @@ Output:
## Nested templates
Like we write code, some part of template is the same in several templates, like header and footer of a blog, so we can define `header`, `content` and `footer` these 3 parts. Go uses following syntax to declare sub-template:
Just like in most web applications, certain parts of templates can be reused across other templates, like the headers and footers of a blog. We can declare `header`, `content` and `footer` as sub-templates, and declare them in Go using the following syntax:
{{define "sub-template"}}content{{end}}
Call by following syntax:
The sub-template is called using the following syntax:
{{template "sub-template"}}
A complete example, suppose we have `header.tmpl`, `content.tmpl, `footer.tmpl` these 3 files.
Here's a complete example, supposing that we have the following three files: `header.tmpl`, `content.tmpl` and `footer.tmpl`.
Main template:
@@ -352,16 +352,16 @@ Code:
s1.Execute(os.Stdout, nil)
}
We can see that `template.ParseFiles` parses all nested templates into cache, and every template that is defined by `{{define}}` is independent, they are paralleled in something like map, where key is template name and value is body of template. Then we use `ExecuteTemplate` to execute corresponding sub-template, so that header and footer are independent and content has both of them. But if we try to execute `s1.Execute`, nothing will be outputted because there is no default sub-template available.
Here we can see that `template.ParseFiles` parses all nested templates into cache, and that every template defined by `{{define}}` is independent of one another. They are persisted in something like a map, where the template names are keys and the values are the template bodies. We can then use `ExecuteTemplate` to execute the corresponding sub-templates, so that the header and footer are independent and content contains them both. Note that if we try to execute `s1.Execute`, nothing will be outputted because there is no default sub-template available.
Templates in one set knows each other, but you have to parse them for every single set.
Templates in one set know each other, but you must parse them for every single set.
## Summary
In this section, you learned that how to combine dynamic data with templates, including print data in loop, template functions, nested templates, etc. By using templates, we can finish V part of MVC model. In following chapters, we will cover M and C parts.
In this section, you learned how to combine dynamic data with templates using techniques including printing data in loops, template functions and nested templates. By learning about templates, we can conclude discussing the V part of the MVC architecture. In the following chapters, we will cover the M and C aspects of MVC.
## Links
- [Directory](preface.md)
- Previous section: [Regexp](07.3.md)
- Next section: [Files](07.5.md)
- Next section: [Files](07.5.md)