Go
Текст + HTML-шаблон
Поиск…
Шаблон одного элемента
Обратите внимание на использование {{.}}
Для вывода элемента в шаблон.
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")
}
Результаты в:
Dear Professor Jones, How are you?
Шаблон нескольких элементов
Обратите внимание на использование {{range .}}
И {{end}}
для циклического переключения коллекции.
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"})
}
Результаты в:
Dear Harry, Jane, Lisa, George, How are you?
Шаблоны с пользовательской логикой
В этом примере функциональная карта с именем funcMap
предоставляется в шаблон с помощью Funcs()
а затем вызывается внутри шаблона. Здесь функция increment()
используется для того, чтобы обойти недостаток меньшей или равной функции на языке шаблонов. Обратите внимание, как обрабатывается последний элемент в коллекции.
A -
в начале {{-
или end -}}
используется для обрезания пробелов и может использоваться, чтобы сделать шаблон более понятным.
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"})
}
Результаты в:
Dear Harry, Jane, Lisa, and George; How are you?
Шаблоны с структурами
Обратите внимание, как значения полей получены с помощью {{.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})
}
Результаты в:
------------------------------
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-шаблоны
Обратите внимание на другой импорт пакета.
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})
}
Результаты в:
<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>
Как HTML-шаблоны предотвращают проникновение вредоносного кода
Во-первых, вот что может случиться, когда text/template
используется для HTML. Обратите внимание на свойство FirstName
Гарри.
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})
}
Результаты в:
<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>
Вышеприведенный пример, если он доступен из браузера, приведет к выполнению скрипта генерируемого предупреждения. Если вместо этого вместо text/template
html/template
был импортирован html/template
text/template
, скрипт был бы безопасно подвергнут санитарной обработке:
<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>
Второй результат будет выглядеть искаженным при загрузке в браузере, но не приведет к выполнению потенциально вредоносного скрипта.