Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Go
Code

Генерация текста с помощью шаблонов Go

by
Difficulty:IntermediateLength:MediumLanguages:

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Обзор

Текст вокруг нас как разработчиков программного обеспечения. Код - это текст, HTML - это текст, XML / JSON / YAML / TOML - это текст, Markdown - это текст, CSV - это текст. Все эти текстовые форматы предназначены для людей и машин. Люди должны иметь возможность читать и редактировать текстовые форматы с помощью текстовых редакторов.

Но во многих случаях вам нужно генерировать текст в определенном формате. Вы можете конвертировать из одного формата в другой, создать свой собственный DSL, автоматически сгенерировать некоторый вспомогательный код или просто настроить электронную почту с информацией для конкретного пользователя. Независимо от того, что вам нужно, Go более чем способен помочь вам на этом пути с его мощными шаблонами.

В этом учебном пособии вы узнаете о плюсах и минусах шаблонов Go и о том, как использовать их для мощной генерации текста.

Что такое шаблоны Go?

Шаблоны Go - это объекты, которые управляют некоторым текстом с помощью специальных заполнителей, называемых действиями, которые заключены в двойные фигурные скобки: {{some action}}. Когда вы выполняете шаблон, вы предоставляете ему структуру Go, которая содержит данные, необходимые для заполнителей.

Вот быстрый пример, который генерирует анекдоты. Шутка тук-тук имеет очень строгий формат. Единственные вещи, которые меняются, это личность молотка и изюминка.

Понимание действий шаблона

Синтаксис шаблона очень мощный, и он поддерживает такие действия, как средства доступа к данным, функции, конвейеры, переменные, условия и циклы.

Средства доступа к данным

Средства доступа к данным очень просты. Они просто извлекают данные из начала структуры. Они также могут углубляться во вложенные структуры:

Если данные не являются структурой, вы можете использовать просто {{.}} Для прямого доступа к значению:

Позже мы увидим, как обращаться с массивами, срезами и картами.

Функции

Функции действительно улучшают то, что вы можете делать с шаблонами. Существует много глобальных функций, и вы даже можете добавить функции, специфичные для шаблона. Полный список глобальных функций доступен на веб-сайте Go.

Вот пример того, как использовать функцию printf в шаблоне:

Пайплайны

Конвейеры позволяют применять несколько функций к текущему значению. Объединение различных функций значительно расширяет способы, с помощью которых вы можете нарезать и нарезать свои значения.

В следующем коде я объединяю три функции. Сначала функция вызова выполняет передачу функции в Execute(). Затем функция len возвращает длину результата функции ввода, которая в данном случае равна 3. Наконец, функция printf печатает количество элементов.

Переменные

Иногда вы хотите многократно использовать результат сложного конвейера. С помощью шаблонов Go вы можете определить переменную и использовать ее столько раз, сколько захотите. В следующем примере извлекаются имя и фамилия из входной структуры, заключаются в кавычки и сохраняются в переменных $F и $L. Затем он отображает их в обычном и обратном порядке.

Еще один полезный трюк заключается в том, что я передаю анонимную структуру в шаблон, чтобы сделать код более лаконичным и избежать загромождения его типами, которые используются только в одном месте.

Условия

Но давайте не будем останавливаться на достигнутом. Вы даже можете иметь условия в своих шаблонах. Существует действие if-end и действие if-else-end. Предложение if отображается, если выходные данные условного конвейера не пусты:

Обратите внимание, что предложение else вызывает новую строку, а текст «Нет данных» имеет значительный отступ.

Циклы

В шаблонах Go тоже есть циклы. Это очень полезно, когда ваши данные содержат фрагменты, карты или другие итерации. Объектом данных для цикла может быть любой итеративный объект Go, например массив, фрагмент, карта или канал. Функция range позволяет перебирать объект данных и создавать выходные данные для каждого элемента. Давайте посмотрим, как перебрать карту:

Как вы можете видеть, ведущие пробелы все еще являются проблемой. Я не смог найти достойного способа решения этой проблемы в синтаксисе шаблона. Это потребует постобработки. Теоретически вы можете поместить тире, чтобы обрезать пропуски перед или после действий, но это не работает при наличии range.

Текстовые шаблоны

Текстовые шаблоны реализованы в пакете text/template. В дополнение ко всему, что мы видели до сих пор, этот пакет может также загружать шаблоны из файлов и составлять несколько шаблонов, используя действие шаблона. Сам объект Template имеет много методов для поддержки таких расширенных вариантов использования:

  • ParseFiles()
  • ParseGlob()
  • AddParseTree()
  • Clone()
  • DefinedTemplates()
  • Delims()
  • ExecuteTemplate()
  • Funcs()
  • Lookup()
  • Option()
  • Templates()

Из-за нехватки места я не буду вдаваться в подробности (возможно, в другом уроке).

HTML-шаблоны

Шаблоны HTML определены в пакете html/template. Он имеет точно такой же интерфейс, что и пакет текстового шаблона, но он предназначен для генерации HTML, который защищен от внедрения кода. Это делается путем тщательной очистки данных перед их внедрением в шаблон. Рабочим предположением является то, что авторам шаблонов доверяют, но данные, предоставленные шаблону, нельзя доверять.

Это важно. Если вы автоматически применяете шаблоны, полученные из ненадежных источников, пакет html/template вас не защитит. Вы несете ответственность за проверку шаблонов.

Давайте посмотрим на разницу между выводом text/template и html/template. При использовании text/template легко внедрить код JavaScript в сгенерированный вывод.

Но импорт html/template вместо text/template предотвращает эту атаку, избегая тегов сценария и скобок:

Работа с ошибками

Существует два типа ошибок: ошибки синтаксического анализа и ошибки выполнения. Функция Parse() анализирует текст шаблона и возвращает ошибку, которую я игнорировал в примерах кода, но в рабочем коде вы хотите отлавливать эти ошибки заранее и исправлять их.

Если вы хотите быстрый и грязный выход, то метод Must() принимает выходные данные метода, который возвращает (* Template, error) - как Clone(), Parse() или ParseFiles() - и паникует, если ошибка не ноль. Вот как вы проверяете явную ошибку разбора:

Использование Must() просто паникует, если что-то не так с шаблоном:

Другой вид ошибки - ошибка выполнения, если предоставленные данные не соответствуют шаблону. Опять же, вы можете проверить явно или использовать Must() для паники. В этом случае я рекомендую вам проверить и установить механизм восстановления.

Обычно нет необходимости разрушать всю систему только потому, что входные данные не соответствуют требованиям. В следующем примере шаблон ожидает поле с именем Name в структуре данных, но я предоставляю структуру с полем с именем FullName.

Заключение

Go имеет мощную и сложную систему шаблонов. Он используется с большим эффектом во многих крупных проектах, таких как Kubernetes и Hugo. Пакет html/template обеспечивает безопасное промышленное средство для очистки результатов веб-систем. В этом уроке мы рассмотрели все основы и некоторые промежуточные варианты использования.

В пакетах шаблонов есть еще более продвинутые функции. Поиграйте с шаблонами и включите их в свои программы. Вы будете приятно удивлены, насколько лаконичным и читабельным выглядит ваш код для генерации текста.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.