Как сгенерировать HTML с помощью шаблонов Golang


Ниже вы можете увидеть веб-страницу, которую мы создадим с помощью GO в данной статье :

Веб-страница является адаптивной, она адаптируется к разной ширине экрана, и когда вы нажимаете на один из «продуктов», вы увидите всплывающее окно с описанием продукта и кнопками.

Я сначала покажу вам программу, которая будет анализировать и отображать шаблоны, а затем выводить сгенерированный HTML-файл. После этого я покажу вам, как выглядят разные шаблоны, и расскажу о некоторых методах, которые я использовал в них.

Golang код
Вот программа Golang, которая сделает всю работу:

package main

import (
    "bufio"
    "bytes"
    "html/template"
    "os"
)

type product struct {
    Img         string
    Name        string
    Price       string
    Stars       float64
    Reviews     int
    Description string
}

func subtr(a, b float64) float64 {
    return a - b
}

func list(e ...float64) []float64 {
    return e
}

func main() {

    data := []product{
        {"images/1.png", "strawberries", "$2.00", 4.0, 251, "Lorem ipsum dolor sit amet, consectetur adipiscing elit."},
        {"images/2.png", "onions", "$2.80", 5.0, 123, "Morbi sit amet erat vitae purus consequat vehicula nec sit amet purus."},
        {"images/3.png", "tomatoes", "$3.10", 4.5, 235, "Curabitur tristique odio et nibh auctor, ut sollicitudin justo condimentum."},
        {"images/4.png", "courgette", "$1.20", 4.0, 251, "Phasellus at leo a purus consequat ornare ac aliquam quam."},
        {"images/5.png", "broccoli", "$3.80", 3.5, 123, "Maecenas sed ante sagittis, dapibus dui quis, hendrerit orci."},
        {"images/6.png", "potatoes", "$3.00", 2.5, 235, "Vivamus malesuada est et tellus porta, vel consectetur orci dapibus."},
    }

    allFiles := []string{"content.tmpl", "footer.tmpl", "header.tmpl", "page.tmpl"}

    var allPaths []string
    for _, tmpl := range allFiles {
        allPaths = append(allPaths, "./templates/"+tmpl)
    }

    templates := template.Must(template.New("").Funcs(template.FuncMap{"subtr": subtr, "list": list}).ParseFiles(allPaths...))

    var processed bytes.Buffer
    templates.ExecuteTemplate(&processed, "page", data)

    outputPath := "./static/index.html"
    f, _ := os.Create(outputPath)
    w := bufio.NewWriter(f)
    w.WriteString(string(processed.Bytes()))
    w.Flush()

}

В строках 3–8 мы импортируем необходимые пакеты. Пакеты bufio, bytes и os необходимы для вывода файла HTML.

Пакет html/template используется для работы с шаблонами.
В строках 10–17 мы определяем product — структуру для хранения данных о продукте. Убедитесь, что все свойства написаны заглавными буквами, т. е. что их можно экспортировать. Это необходимо при использовании структуры внутри шаблонов Golang.
Также обратите внимание, что количество звездочек — это число с плавающей запятой от 0 до 5. Причина, по которой мы используем тип float64 для этого числа, заключается в том, что шаблоны используют float64 для всех чисел с плавающей запятой.
В строках 19–25 я создал две функции. Первая функция, называемая subtr(), представляет собой простую функцию вычитания чисел с плавающей запятой, а вторая функция, называемая list(), используется для создания списка чисел с плавающей запятой.
В строках 29–36 мы определяем данные, которые будут отображаться в шаблонах. В этом примере данные жестко запрограммированы. В более реалистичных условиях эти данные, вероятно, будут храниться в какой-либо базе данных.
В строке 38 мы добавляем имена файлов всех шаблонов в слайс.
В строках 40–43 ко всем именам файлов добавляется имя каталога /templates/.
В строке 45 мы анализируем шаблоны с помощью ParseFiles(), обязательно добавляем две функции subtr и list с помощью template.FuncMap{} и проверяем правильность шаблонов с помощью template.Must().
В строках 47–48 мы отображаем шаблоны в байтовый буфер. Чтобы убедиться, что рендеринг начинается с шаблона страницы, мы используем ExecuteTemplates() со «страницей» в качестве аргумента. Здесь мы также передаем данные, которые мы определили средству визуализации.
В строках 50–54 обработанный байтовый буфер выводится в файл HTML с именем index.html в каталоге ./static.

Шаблоны для генерации HTML
Здесь мы обсудим все шаблоны, используемые для этого проекта.


Шаблон «page»(страница)
Это шаблон, который определяет полную веб-страницу. Он вызывает три других шаблона; headercontent, and footer (заголовок, содержимое и нижний колонтитул).

{{define "page"}}
{{template "header" -}}
{{template "content" . -}}
{{template "footer" -}}
{{end}}

В строке 1 необходимо определить страницу внутри этого шаблона, иначе метод ExecuteTemplates() ее не найдет.
Обратите внимание, что в строке 3 при вызове шаблона контента добавляется точка. Это сигнализирует обработчику шаблона, что предоставленные данные должны быть отправлены вместе с шаблоном контента. Это то же самое, что и передача параметров функции.

Шаблон «header»
Этот шаблон используется для отображения типичного заголовка HTML, который загружает шрифты, стили и код JavaScript.

{{define "header" -}}
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
   <link rel="stylesheet" href="css/style.css">
   <script src="js/script.js" defer></script>
</head>
<body>
{{end}}

Обратите внимание, что мы используем ключевые слова define и end для определения шаблона .
Также обратите внимание на знак «-» перед двойными закрывающими скобками. Этот знак указывает средству визуализации удалить пробелы и символы новой строки. По моему опыту, вам нужно поэкспериментировать с использование этих «-», чтобы лучше понять их использование.
Чтобы добиться желаемого результата, вам иногда нужно поставить «-» после двойных скобок, иногда перед двойными конечными скобками, а иногда и в обоих местах.


Шаблон «content»
Это шаблон, который отображает тело HTML-файла.
С данным шаблоном мы можем быстро создавать другие страницы с другим содержимым, но с тем же верхним и нижним колонтитулами, т. е. загружая те же CSS, JS, шрифты и т. д.

{{define "content" -}}
<div class="container">
   <h3 class="title"> organic products </h3>
   <div class="products-container">
{{range $index, $item :=.}}
      <div class="product" data-name="p-{{$index}}">
         <img src="{{$item.Img}}" alt="">
         <h3>{{$item.Name}}</h3>
         <div class="price">{{$item.Price}}</div>
      </div>
{{end}}
   </div>
</div>

<div class="products-preview">
{{range $index, $item:=.}}
  <div class="preview" data-target="p-{{$index}}">
      <i class="fas fa-times"></i>
      <img src="{{$item.Img}}" alt="">
      <h3>organic {{$item.Name}}</h3>
      <div class="stars">
      {{- $stars := list 1.0 2.0 3.0 4.0 5.0 -}}
      {{- range $stars}}
            {{$x:= subtr . 0.5}}
            {{- if lt $item.Stars $x -}}
            <i class="far fa-star"></i>
            {{- else if lt $item.Stars . -}}
            <i class="fas fa-star-half-alt"></i>
            {{- else -}}
            <i class="fas fa-star"></i>
            {{- end -}}
      {{end}}
         <span>( {{$item.Reviews}} )</span>
      </div>
      <p>{{$item.Description}}</p>
      <div class="price">{{$item.Price}}</div>
      <div class="buttons">
         <a href="#" class="buy">buy now</a>
         <a href="#" class="cart">add to cart</a>
      </div>
   </div>
{{end}}
</div>
{{end}}

В строках 5–12 мы перебираем все продукты . Для каждого продукта мы создаем внутренние переменные шаблона $index и $item. Мы используем $index для атрибута имени данных. Из $item мы извлекаем свойства Img, Name и Price для использования в HTML.
В строках 16–42 мы делаем то же самое, что и выше, но также извлекаем свойства $Stars $Description и $Reviews из $item.
В строке 22 мы создаем список с именем $stars. Этот список содержит числа с плавающей запятой от 1,0 до 5,0. Они понадобятся нам для отображения рейтинга(звезд). Эти числа представляют собой пороговое значение для отображения каждой звезды.
Затем в строках 23–32 мы создаем цикл для отображения рейтинга(звезд). По сути, у нас есть три типа звезд, которые мы можем отображать: полные звезды, половина звезды и пустые звезды.

Шаблон «footer»
Здесь ничего особенного не происходит, кроме определения шаблона как нижнего колонтитула.

{{define "footer" -}}
</body>
</html>
{{end}}

Запуск генератора HTML и просмотр результата
Убедитесь, что файл main.go находится в каталоге, который также содержит два подкаталога с именами templates и static. Все вышеперечисленные шаблоны должны находиться в каталоге шаблонов. CSS, JS и изображения из исходного кода должны находиться в соответствующих подкаталогах статического каталога.
Просто введите go run main.go из нужного каталога в вашем терминале, чтобы запустить генератор. Впоследствии файл HTML будет сгенерирован и записан в статический каталог как index.html.
Теперь вы можете открыть файл index.html в своем браузере, и вы должны получить веб страницу, показанную в начале этой статьи.

Ответить