В данной статье мы рассмотрим операторы и функции при работе с шаблонами, которые предоставляет шаблонизатор от Go.
Мы уже использовали некоторые операторы в прошлой статье, а точнее {{define}}
, {{template}}
и {{block}}
. Однако есть еще три оператора, которые можно использовать для управления отображением динамических данных на странице — {{if}}
, {{with}}
и {{range}}
.
Рекомендуем вам супер TELEGRAM канал по Golang где собраны все материалы для качественного изучения языка. Удивите всех своими знаниями на собеседовании! 😎
Мы публикуем в паблике ВК и Telegram качественные обучающие материалы для быстрого изучения Go. Подпишитесь на нас в ВК и в Telegram. Поддержите сообщество Go программистов.
Синтаксис оператора | Описание | ||||
|
Если .Foo содержит какой либо контент, тогда отображается содержимое из C1 , в противном случае отображается содержимое из С2 . |
||||
|
Содержимое из структуры userdata передаётся в точку . и уже в теле оператора when до его загружающего тега {{ end }} доступ к полям из структуры userdata выполняется сразу через точку .Name , чтобы не писать каждый раз .usernata.Name . Тут оператор when полностью схож с оператором when из языка программирования Python. |
||||
или
|
Оператор range выполняет цикл по перебору данных из среза. Допустим у нас есть срез данных с клиентами и мы хотим вывести весь список клиентов на странице.
|
Пример нашей структуры и сраза с данными клиентов для {{ range }}
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
type Clients struct { Name string Money int } func main() { clients := []Clients{ {Name: "Иван", Money: 100}, {Name: "Андрей", Money: 1500}, {Name: "Василий", Money: 500}, } // тут у нас подготовка файлов шаблона и рендеринг. } |
Стоит отметить несколько моментов, связанных с данными операторами:
- Для всех трех операторов, условие
{{else}}
необязательно. Например, можно написать{{if .Foo}} C1 {{end}}
, если нет содержимогоC2
, которое нужно отобразить; - Пустыми значениями являются false, 0, любой указатель nil или значение интерфейса, а также любой массив, срез, карта или строка нулевой длины;
- Важно отметить, что оператор
with
иrange
меняют содержимое.
точки.
Пакет html/template
также предоставляет некоторые функции, которые вы можете использовать для добавления дополнительной логики в шаблоны и управления тем, что отображается при рендеринге шаблона. Найти полный список функций можно здесь.
Далее представлены самые важные функции от шаблонизатора:
Функция | Описание |
{{eq .Foo .Bar}} |
Возвращает true , если .Foo равно .Bar |
{{ne .Foo .Bar}} |
Возвращает true , если .Foo не равно .Bar |
{{not .Foo}} |
Возвращает булево отрицание .Foo |
{{or .Foo .Bar}} |
Возвращает .Foo , если .Foo не пустое, в противном случае выдает .Bar |
{{index .Foo i}} |
Возвращает значение из .Foo по индексу i . Базовый тип .Foo должен быть картой, срезом или массивом |
{{printf "%s-%s" .Foo .Bar}} |
Возвращает отформатированную строку, содержащую значения .Foo и .Bar . Работает так же, как fmt.Sprintf() |
{{len .Foo}} |
Возвращает длину символов .Foo как integer |
{{$bar := len .Foo}} |
Присваивает длину .Foo переменной шаблона $bar |
Последний ряд представляет собой пример объявления переменной в шаблоне. Переменные в шаблоне особенно полезны, если требуется сохранить результат из функции и использовать его в логике отображения шаблона. Названия переменных должны начинаться со знака доллара и содержать только буквенно-цифровые символы.
Оператор with от golang шаблонизатора
Хорошей возможностью использовать оператор {{with}}
является наш файл show.page.tmpl
, который мы создали в предыдущем уроке.
Измените его структуру следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{{template "base" .}} {{define "title"}}Заметка #{{.Snippet.ID}}{{end}} {{define "main"}} {{with .Snippet}} <div class='snippet'> <div class='metadata'> <strong>{{.Title}}</strong> <span>#{{.ID}}</span> </div> <pre><code>{{.Content}}</code></pre> <div class='metadata'> <time>Создан: {{.Created}}</time> <time>Срок: {{.Expires}}</time> </div> </div> {{end}} {{end}} |
Теперь между {{with .Snippet}}
и его закрывающим тегом {{end}}
содержимое точки .
хранит в себе содержимое от структуры Snippet
. По сути точка становится структурой models.Snippet
вместо структуры templateData
которая изначально хранилась в этой точки.
Оператор if-else и range от шаблонизатора
В качестве примера давайте воспользуемся операторами {{if}}
и {{range}}
и обновим домашнюю страницу нашего веб-приложения для отображения таблицы с последними заметками. Результат будет выглядеть примерно следующим образом:
Сначала обновим структуру templateData
, чтобы она содержала новое поле Snippets
в ней будет срез со всеми заметками из базы данных. Сделаем это следующим образом:
1 2 3 4 5 6 7 8 9 |
package main import "golangify.com/snippetbox/pkg/models" // Добавляем поле Snippets в структуру templateData type templateData struct { Snippet *models.Snippet Snippets []*models.Snippet } |
Затем обновляем обработчик home
, чтобы он извлёк последние заметки из модели базы данных и передал их в шаблон home.page.tmpl
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
func (app *application) home(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { app.notFound(w) return } s, err := app.snippets.Latest() if err != nil { app.serverError(w, err) return } // Создаем экземпляр структуры templateData, // содержащий срез с заметками. data := &templateData{Snippets: s} files := []string{ "./ui/html/home.page.tmpl", "./ui/html/base.layout.tmpl", "./ui/html/footer.partial.tmpl", } ts, err := template.ParseFiles(files...) if err != nil { app.serverError(w, err) return } // Передаем структуру templateData в шаблонизатор. // Теперь она будет доступна внутри файлов шаблона через точку. err = ts.Execute(w, data) if err != nil { app.serverError(w, err) } } |
Теперь давайте перейдем к файлу ui/html/home.page.tmpl
и обновим его содержимое для отображения этих заметок в таблице с помощью операторов {{if}}
и {{range}}
.
В частности:
- Мы хотим использовать оператор
{{if}}
, чтобы проверить, содержится какие либо данные в срезеsnippets
или нет. Если он пуст, мы напишем пользователю следующееЗдесь ничего нет... пока что!
. В противном случае нужно отобразить таблицу, содержащую информацию о заметках; - Мы хотим использовать оператор
{{range}}
для перебора всех заметок в срезе и отображение их в виде таблицы.
Вот разметка:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
{{template "base" .}} {{define "title"}}Домашняя страница{{end}} {{define "main"}} <h2>Последние Заметки</h2> {{if .Snippets}} <table> <tr> <th>Заголовок</th> <th>Создан</th> <th>ID</th> </tr> {{range .Snippets}} <tr> <td><a href='/snippet?id={{.ID}}'>{{.Title}}</a></td> <td>{{.Created}}</td> <td>#{{.ID}}</td> </tr> {{end}} </table> {{else}} <p>Здесь ничего нет... пока что!</p> {{end}} {{end}} |
Ниже будет приведен пример, чтобы вы знали как еще можно итерировать срез в шаблоне используя {{ range }}
путем создания новых переменных $key
и $snippet
.
1 2 3 4 5 6 7 |
{{ range $key, $snippet := .Snippets }} <tr> <td><a href='/snippet?id={{ $snippet.ID }}'>{{ $snippet.Title }}</a></td> <td>{{ $snippet.Created }}</td> <td>#{{ $snippet.ID }}</td> </tr> {{end}} |
В нашем приложении мы будем использовать первый вариант, где данные заметки передаются сразу в .
точку.
Убедитесь, что ваши файлы сохранены и перезапустите веб-приложение. Перейдите на страницу http://127.0.0.1:4000 в браузере. Если все прошло по плану, вы должны увидеть страницу, похожую на следующую:
Скачать исходный код
В конце каждого урока мы даём исходный код нашего приложения на текущий момент развития.
Скачать: snippetbox-24
Администрирую данный сайт с целью распространения как можно большего объема обучающего материала для языка программирования Go. В IT с 2008 года, с тех пор изучаю и применяю интересующие меня технологии. Проявляю огромный интерес к машинному обучению и анализу данных.
E-mail: vasile.buldumac@ati.utm.md
Образование
Технический Университет Молдовы (utm.md), Факультет Вычислительной Техники, Информатики и Микроэлектроники
- 2014 — 2018 Universitatea Tehnică a Moldovei, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Universitatea Tehnică a Moldovei, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»