Go
Text + HTML Templating
Sök…
Enstaka mall
Notera att {{.}}
Används för att mata ut objektet i mallen.
package main
import (
"fmt"
"os"
"text/template"
)
func main() {
const (
letter = `Dear {{.}}, How are you?`
)
tmpl, err := template.New("letter").Parse(letter)
if err != nil {
fmt.Println(err.Error())
}
tmpl.Execute(os.Stdout, "Professor Jones")
}
Resulterar i:
Dear Professor Jones, How are you?
Mall för flera objekt
Observera användningen av {{range .}}
Och {{end}}
att cykla över samlingen.
package main
import (
"fmt"
"os"
"text/template"
)
func main() {
const (
letter = `Dear {{range .}}{{.}}, {{end}} How are you?`
)
tmpl, err := template.New("letter").Parse(letter)
if err != nil {
fmt.Println(err.Error())
}
tmpl.Execute(os.Stdout, []string{"Harry", "Jane", "Lisa", "George"})
}
Resulterar i:
Dear Harry, Jane, Lisa, George, How are you?
Mallar med anpassad logik
I det här exemplet levereras en funktionskarta med namnet funcMap
till mallen via Funcs()
och anropas sedan inuti mallen. Här används funktionsökningen increment()
för att komma runt bristen på en mindre än eller lika funktion i templateringsspråket. Notera i utgången hur det sista objektet i samlingen hanteras.
A -
i början {{-
eller slutet -}}
används för att trimma mellanrum och kan användas för att göra mallen läsbarare.
package main
import (
"fmt"
"os"
"text/template"
)
var funcMap = template.FuncMap{
"increment": increment,
}
func increment(x int) int {
return x + 1
}
func main() {
const (
letter = `Dear {{with $names := .}}
{{- range $i, $val := $names}}
{{- if lt (increment $i) (len $names)}}
{{- $val}}, {{else -}} and {{$val}}{{end}}
{{- end}}{{end}}; How are you?`
)
tmpl, err := template.New("letter").Funcs(funcMap).Parse(letter)
if err != nil {
fmt.Println(err.Error())
}
tmpl.Execute(os.Stdout, []string{"Harry", "Jane", "Lisa", "George"})
}
Resulterar i:
Dear Harry, Jane, Lisa, and George; How are you?
Mallar med strukturer
Lägg märke till hur fältvärden erhålls med {{.FieldName}}
.
package main
import (
"fmt"
"os"
"text/template"
)
type Person struct {
FirstName string
LastName string
Street string
City string
State string
Zip string
}
func main() {
const (
letter = `------------------------------
{{range .}}{{.FirstName}} {{.LastName}}
{{.Street}}
{{.City}}, {{.State}} {{.Zip}}
Dear {{.FirstName}},
How are you?
------------------------------
{{end}}`
)
tmpl, err := template.New("letter").Parse(letter)
if err != nil {
fmt.Println(err.Error())
}
harry := Person{
FirstName: "Harry",
LastName: "Jones",
Street: "1234 Main St.",
City: "Springfield",
State: "IL",
Zip: "12345-6789",
}
jane := Person{
FirstName: "Jane",
LastName: "Sherman",
Street: "8511 1st Ave.",
City: "Dayton",
State: "OH",
Zip: "18515-6261",
}
tmpl.Execute(os.Stdout, []Person{harry, jane})
}
Resulterar i:
------------------------------
Harry Jones
1234 Main St.
Springfield, IL 12345-6789
Dear Harry,
How are you?
------------------------------
Jane Sherman
8511 1st Ave.
Dayton, OH 18515-6261
Dear Jane,
How are you?
------------------------------
HTML-mallar
Observera den olika paketimporten.
package main
import (
"fmt"
"html/template"
"os"
)
type Person struct {
FirstName string
LastName string
Street string
City string
State string
Zip string
AvatarUrl string
}
func main() {
const (
letter = `<html><body><table>
<tr><th></th><th>Name</th><th>Address</th></tr>
{{range .}}
<tr>
<td><img src="{{.AvatarUrl}}"></td>
<td>{{.FirstName}} {{.LastName}}</td>
<td>{{.Street}}, {{.City}}, {{.State}} {{.Zip}}</td>
</tr>
{{end}}
</table></body></html>`
)
tmpl, err := template.New("letter").Parse(letter)
if err != nil {
fmt.Println(err.Error())
}
harry := Person{
FirstName: "Harry",
LastName: "Jones",
Street: "1234 Main St.",
City: "Springfield",
State: "IL",
Zip: "12345-6789",
AvatarUrl: "harry.png",
}
jane := Person{
FirstName: "Jane",
LastName: "Sherman",
Street: "8511 1st Ave.",
City: "Dayton",
State: "OH",
Zip: "18515-6261",
AvatarUrl: "jane.png",
}
tmpl.Execute(os.Stdout, []Person{harry, jane})
}
Resulterar i:
<html><body><table>
<tr><th></th><th>Name</th><th>Address</th></tr>
<tr>
<td><img src="harry.png"></td>
<td>Harry Jones</td>
<td>1234 Main St., Springfield, IL 12345-6789</td>
</tr>
<tr>
<td><img src="jane.png"></td>
<td>Jane Sherman</td>
<td>8511 1st Ave., Dayton, OH 18515-6261</td>
</tr>
</table></body></html>
Hur HTML-mallar förhindrar injektion av skadlig kod
Först, här är vad som kan hända när text/template
används för HTML. Observera Harrys FirstName
egenskap).
package main
import (
"fmt"
"html/template"
"os"
)
type Person struct {
FirstName string
LastName string
Street string
City string
State string
Zip string
AvatarUrl string
}
func main() {
const (
letter = `<html><body><table>
<tr><th></th><th>Name</th><th>Address</th></tr>
{{range .}}
<tr>
<td><img src="{{.AvatarUrl}}"></td>
<td>{{.FirstName}} {{.LastName}}</td>
<td>{{.Street}}, {{.City}}, {{.State}} {{.Zip}}</td>
</tr>
{{end}}
</table></body></html>`
)
tmpl, err := template.New("letter").Parse(letter)
if err != nil {
fmt.Println(err.Error())
}
harry := Person{
FirstName: `Harry<script>alert("You've been hacked!")</script>`,
LastName: "Jones",
Street: "1234 Main St.",
City: "Springfield",
State: "IL",
Zip: "12345-6789",
AvatarUrl: "harry.png",
}
jane := Person{
FirstName: "Jane",
LastName: "Sherman",
Street: "8511 1st Ave.",
City: "Dayton",
State: "OH",
Zip: "18515-6261",
AvatarUrl: "jane.png",
}
tmpl.Execute(os.Stdout, []Person{harry, jane})
}
Resulterar i:
<html><body><table>
<tr><th></th><th>Name</th><th>Address</th></tr>
<tr>
<td><img src="harry.png"></td>
<td>Harry<script>alert("You've been hacked!")</script> Jones</td>
<td>1234 Main St., Springfield, IL 12345-6789</td>
</tr>
<tr>
<td><img src="jane.png"></td>
<td>Jane Sherman</td>
<td>8511 1st Ave., Dayton, OH 18515-6261</td>
</tr>
</table></body></html>
Exemplet ovan, om åtkomst från en webbläsare, skulle resultera i att skriptet körs en varning som genereras. Om html/template
istället importerades istället för text/template
, skulle skriptet saneras på ett säkert sätt:
<html><body><table>
<tr><th></th><th>Name</th><th>Address</th></tr>
<tr>
<td><img src="harry.png"></td>
<td>Harry<script>alert("You've been hacked!")</script> Jones</td>
<td>1234 Main St., Springfield, IL 12345-6789</td>
</tr>
<tr>
<td><img src="jane.png"></td>
<td>Jane Sherman</td>
<td>8511 1st Ave., Dayton, OH 18515-6261</td>
</tr>
</table></body></html>
Det andra resultatet ser snyggt ut när det laddas i en webbläsare, men skulle inte resultera i ett potentiellt skadligt skript som körs.