Шпаргалка по html/template в Go

html/template - это пакет Go для безопасного создания HTML-выхода с автоматическим экранированием.

Инициализация шаблона

import "html/template"

// Создание нового шаблона
tmpl := template.New("templateName")

// Парсинг шаблона из строки
tmpl, err := template.New("test").Parse(`<h1>{{.Title}}</h1>`)

// Парсинг шаблона из файла
tmpl, err := template.ParseFiles("template.html")

// Парсинг нескольких файлов
tmpl, err := template.ParseGlob("templates/*.html")

Основные конструкции в шаблоне

1. Вывод значения

<!-- Простой вывод -->
<p>{{.UserName}}</p>

<!-- Вывод с экранированием HTML -->
<p>{{.UserComment}}</p>

<!-- Вывод без экранирования (осторожно!) -->
<p>{{.SafeHTML | html}}</p>

2. Условия

{{if .User}}
    <p>Welcome, {{.User}}!</p>
{{else}}
    <p>Please log in.</p>
{{end}}

{{if eq .Role "admin"}}
    <p>Admin dashboard</p>
{{end}}

3. Циклы

<ul>
{{range .Items}}
    <li>{{.}}</li>
{{end}}
</ul>

<!-- С индексом -->
<ul>
{{range $index, $item := .Items}}
    <li>Item #{{$index}}: {{$item}}</li>
{{end}}
</ul>

<!-- Если слайс пуст -->
{{range .Items}}
    {{.}}
{{else}}
    <p>No items found</p>
{{end}}

4. Определение переменных

{{$name := .UserName}}
{{$count := len .Items}}
<p>Hello, {{$name}}. You have {{$count}} items.</p>

5. Функции и конвейеры

<!-- Вызов встроенных функций -->
<p>{{printf "Hello, %s" .Name}}</p>
<p>{{len .Items}} items</p>
<p>{{index .Items 0}}</p>

<!-- Конвейер -->
<p>{{.Title | upper | truncate 50}}</p>

6. Вложенные шаблоны

// Определение в коде
tmpl := template.Must(template.New("base").Parse(`
{{define "content"}}Default content{{end}}
<html>
<body>
    {{template "content" .}}
</body>
</html>
`))

// Переопределение в другом шаблоне
tmpl2 := template.Must(tmpl.Parse(`{{define "content"}}New content{{end}}`))
<!-- В шаблоне -->
{{template "header" .}}

<!-- С передачей других данных -->
{{template "footer" .FooterData}}

7. Пользовательские функции

funcMap := template.FuncMap{
    "upper": strings.ToUpper,
    "add": func(a, b int) int { return a + b },
}

tmpl := template.New("test").Funcs(funcMap)
tmpl, err := tmpl.Parse(`{{upper .Name}} {{add 1 2}}`)

Пример полного шаблона

<!DOCTYPE html>
<html>
<head>
    <title>{{.Title}} - My Site</title>
</head>
<body>
    <header>
        {{if .User}}
            <p>Welcome, {{.User.Name}} ({{.User.Email}})</p>
        {{else}}
            <a href="/login">Login</a>
        {{end}}
    </header>
    
    <nav>
        <ul>
            {{range .Menu}}
                <li><a href="{{.URL}}">{{.Title}}</a></li>
            {{end}}
        </ul>
    </nav>
    
    <main>
        {{template "content" .}}
    </main>
    
    <footer>
        <p>© {{.CurrentYear}} My Company</p>
    </footer>
</body>
</html>

Выполнение шаблона

// В память
err := tmpl.Execute(os.Stdout, data)

// В строку
var buf bytes.Buffer
err := tmpl.Execute(&buf, data)
result := buf.String()

// Конкретный шаблон из набора
err := tmpl.ExecuteTemplate(os.Stdout, "templateName", data)

Обработка ошибок

tmpl := template.Must(template.New("").Parse("...")) // паника при ошибке

if err := tmpl.Execute(w, data); err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
}

Безопасность

  • Автоматическое экранирование HTML/JS/CSS
  • Для отключения экранирования используйте типы template.HTML, template.JS, template.CSS:
type Data struct {
    SafeContent template.HTML
}

data := Data{SafeContent: template.HTML("<b>Safe HTML</b>")}