diff --git a/en/07.4.md b/en/07.4.md index c8c3e268d..5a4a1bf0e 100644 --- a/en/07.4.md +++ b/en/07.4.md @@ -17,12 +17,12 @@ In Go, we have the `template` package to help handle templates. We can use funct Example: ```Go - func handler(w http.ResponseWriter, r *http.Request) { - t := template.New("some template") // Create a template. - t, _ = t.ParseFiles("tmpl/welcome.html", nil) // Parse template file. - user := GetUser() // Get current user infomration. - t.Execute(w, user) // merge. - } +func handler(w http.ResponseWriter, r *http.Request) { + t := template.New("some template") // Create a template. + t, _ = t.ParseFiles("tmpl/welcome.html", nil) // Parse template file. + user := GetUser() // Get current user infomration. + t.Execute(w, user) // merge. +} ``` As you can see, it's very easy to use, load and render data in templates in Go, just as in other programming languages. @@ -40,32 +40,32 @@ We've just shown you how to parse and render templates. Let's take it one step f 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: ```Go - package main - - import ( - "html/template" - "os" - ) - - type Person struct { - UserName string - } - - func main() { - t := template.New("fieldname example") - t, _ = t.Parse("hello {{.UserName}}!") - p := Person{UserName: "Astaxie"} - t.Execute(os.Stdout, p) - } +package main + +import ( + "html/template" + "os" +) + +type Person struct { + UserName string +} + +func main() { + t := template.New("fieldname example") + t, _ = t.Parse("hello {{.UserName}}!") + p := Person{UserName: "Astaxie"} + t.Execute(os.Stdout, p) +} ``` The above example outputs `hello Astaxie` correctly, but if we modify our struct a little bit, the following error emerges: ```Go - type Person struct { - UserName string - email string // Field is not exported. - } +type Person struct { + UserName string + email string // Field is not exported. +} - t, _ = t.Parse("hello {{.UserName}}! {{.email}}") +t, _ = t.Parse("hello {{.UserName}}! {{.email}}") ``` 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. @@ -80,67 +80,67 @@ We know how to output a field now. What if the field is an object, and it also h More examples: ```Go - package main - - import ( - "html/template" - "os" - ) - - type Friend struct { - Fname string - } - - type Person struct { - UserName string - Emails []string - Friends []*Friend - } - - func main() { - f1 := Friend{Fname: "minux.ma"} - f2 := Friend{Fname: "xushiwei"} - t := template.New("fieldname example") - t, _ = t.Parse(`hello {{.UserName}}! - {{range .Emails}} - an email {{.}} - {{end}} - {{with .Friends}} - {{range .}} - my friend name is {{.Fname}} - {{end}} - {{end}} - `) - p := Person{UserName: "Astaxie", - Emails: []string{"astaxie@beego.me", "astaxie@gmail.com"}, - Friends: []*Friend{&f1, &f2}} - t.Execute(os.Stdout, p) - } +package main + +import ( + "html/template" + "os" +) + +type Friend struct { + Fname string +} + +type Person struct { + UserName string + Emails []string + Friends []*Friend +} + +func main() { + f1 := Friend{Fname: "minux.ma"} + f2 := Friend{Fname: "xushiwei"} + t := template.New("fieldname example") + t, _ = t.Parse(`hello {{.UserName}}! + {{range .Emails}} + an email {{.}} + {{end}} + {{with .Friends}} + {{range .}} + my friend name is {{.Fname}} + {{end}} + {{end}} + `) + p := Person{UserName: "Astaxie", + Emails: []string{"astaxie@beego.me", "astaxie@gmail.com"}, + Friends: []*Friend{&f1, &f2}} + t.Execute(os.Stdout, p) +} ``` ### Conditions 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: ```Go - package main - - import ( - "os" - "text/template" - ) - - func main() { - tEmpty := template.New("template test") - tEmpty = template.Must(tEmpty.Parse("Empty pipeline if demo: {{if ``}} will not be outputted. {{end}}\n")) - tEmpty.Execute(os.Stdout, nil) - - tWithValue := template.New("template test") - tWithValue = template.Must(tWithValue.Parse("Not empty pipeline if demo: {{if `anything`}} will be outputted. {{end}}\n")) - tWithValue.Execute(os.Stdout, nil) - - tIfElse := template.New("template test") - tIfElse = template.Must(tIfElse.Parse("if-else demo: {{if `anything`}} if part {{else}} else part.{{end}}\n")) - tIfElse.Execute(os.Stdout, nil) - } +package main + +import ( + "os" + "text/template" +) + +func main() { + tEmpty := template.New("template test") + tEmpty = template.Must(tEmpty.Parse("Empty pipeline if demo: {{if ``}} will not be outputted. {{end}}\n")) + tEmpty.Execute(os.Stdout, nil) + + tWithValue := template.New("template test") + tWithValue = template.Must(tWithValue.Parse("Not empty pipeline if demo: {{if `anything`}} will be outputted. {{end}}\n")) + tWithValue.Execute(os.Stdout, nil) + + tIfElse := template.New("template test") + tIfElse = template.Must(tIfElse.Parse("if-else demo: {{if `anything`}} if part {{else}} else part.{{end}}\n")) + tIfElse.Execute(os.Stdout, nil) +} ``` As you can see, it's easy to use `if-else` in templates. @@ -184,105 +184,105 @@ Suppose we have an `emailDeal` template function associated with its `EmailDealW Example: ```Go - package main - - import ( - "fmt" - "html/template" - "os" - "strings" - ) - - type Friend struct { - Fname string +package main + +import ( + "fmt" + "html/template" + "os" + "strings" +) + +type Friend struct { + Fname string +} + +type Person struct { + UserName string + Emails []string + Friends []*Friend +} + +func EmailDealWith(args ...interface{}) string { + ok := false + var s string + if len(args) == 1 { + s, ok = args[0].(string) } - - type Person struct { - UserName string - Emails []string - Friends []*Friend + if !ok { + s = fmt.Sprint(args...) } - - func EmailDealWith(args ...interface{}) string { - ok := false - var s string - if len(args) == 1 { - s, ok = args[0].(string) - } - if !ok { - s = fmt.Sprint(args...) - } - // find the @ symbol - substrs := strings.Split(s, "@") - if len(substrs) != 2 { - return s - } - // replace the @ by " at " - return (substrs[0] + " at " + substrs[1]) - } - - func main() { - f1 := Friend{Fname: "minux.ma"} - f2 := Friend{Fname: "xushiwei"} - t := template.New("fieldname example") - t = t.Funcs(template.FuncMap{"emailDeal": EmailDealWith}) - t, _ = t.Parse(`hello {{.UserName}}! - {{range .Emails}} - an emails {{.|emailDeal}} - {{end}} - {{with .Friends}} - {{range .}} - my friend name is {{.Fname}} - {{end}} - {{end}} - `) - p := Person{UserName: "Astaxie", - Emails: []string{"astaxie@beego.me", "astaxie@gmail.com"}, - Friends: []*Friend{&f1, &f2}} - t.Execute(os.Stdout, p) + // find the @ symbol + substrs := strings.Split(s, "@") + if len(substrs) != 2 { + return s } + // replace the @ by " at " + return (substrs[0] + " at " + substrs[1]) +} + +func main() { + f1 := Friend{Fname: "minux.ma"} + f2 := Friend{Fname: "xushiwei"} + t := template.New("fieldname example") + t = t.Funcs(template.FuncMap{"emailDeal": EmailDealWith}) + t, _ = t.Parse(`hello {{.UserName}}! + {{range .Emails}} + an emails {{.|emailDeal}} + {{end}} + {{with .Friends}} + {{range .}} + my friend name is {{.Fname}} + {{end}} + {{end}} + `) + p := Person{UserName: "Astaxie", + Emails: []string{"astaxie@beego.me", "astaxie@gmail.com"}, + Friends: []*Friend{&f1, &f2}} + t.Execute(os.Stdout, p) +} ``` Here is a list of built-in template functions: ```Go - var builtins = FuncMap{ - "and": and, - "call": call, - "html": HTMLEscaper, - "index": index, - "js": JSEscaper, - "len": length, - "not": not, - "or": or, - "print": fmt.Sprint, - "printf": fmt.Sprintf, - "println": fmt.Sprintln, - "urlquery": URLQueryEscaper, - } +var builtins = FuncMap{ + "and": and, + "call": call, + "html": HTMLEscaper, + "index": index, + "js": JSEscaper, + "len": length, + "not": not, + "or": or, + "print": fmt.Sprint, + "printf": fmt.Sprintf, + "println": fmt.Sprintln, + "urlquery": URLQueryEscaper, +} ``` ## 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`: ```Go - package main +package main - import ( - "fmt" - "text/template" - ) +import ( + "fmt" + "text/template" +) - func main() { - tOk := template.New("first") - template.Must(tOk.Parse(" some static text /* and a comment */")) - fmt.Println("The first one parsed OK.") +func main() { + tOk := template.New("first") + template.Must(tOk.Parse(" some static text /* and a comment */")) + fmt.Println("The first one parsed OK.") - template.Must(template.New("second").Parse("some static text {{ .Name }}")) - fmt.Println("The second one parsed OK.") + template.Must(template.New("second").Parse("some static text {{ .Name }}")) + fmt.Println("The second one parsed OK.") - fmt.Println("The next one ought to fail.") - tErr := template.New("check parse error with Must") - template.Must(tErr.Parse(" some static text {{ .Name }")) - } + fmt.Println("The next one ought to fail.") + tErr := template.New("check parse error with Must") + template.Must(tErr.Parse(" some static text {{ .Name }")) +} ``` Output: @@ -306,76 +306,76 @@ Here's a complete example, supposing that we have the following three files: `he Main template: ```html {% raw %} - //header.tmpl - {{define "header"}} - -
-{{.Title}}
-{{.Content}}
- - -No Tasks here
- -{{.Title}}
+{{.Content}}
+ + +No Tasks here
+ +