Как работать с html в golang
Решил написать веб-приложение на golang и столкнулся с вопросом, как правильно работать с html страницами.
Когда пробовал что-то похожее написать на Python, то там создавал base.html, где задавалась общая структура страницы и там где разметка страницы должна меняться, создавал блоки. Далее, подключал base.html вначале другой страницы (например index.html) и добавлял контент в указанные блоки.
Попробовал так же сделать на golang. Создал простой base.html
{{ define "base"}}
<!DOCTYPE html>
<html lang="en">
<head>
<title>
{{block "title" .}}
{{end}}
</title>
</head>
<body>
{{block "content" .}}
{{ end }}
</body>
</html>
{{ end }}
и index.html
{{ define "index" }}
{{ template "header" .}}
{{ define "title" }}
Home
{{ end }}
{{ define "content" }}
<h1> Content </h1>
{{ end }}
{{ end }}
В самом golang вызываю следующую функцию:
func Index(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("templates/base.html", "templates/index.html")
if err != nil {
log.Println("%v : [WARNING] %v", time.Now(), err)
}
err = t.ExecuteTemplate(w, "index", data)
if err != nil {
log.Println("%v : [ERROR] %v", time.Now(), err)
}
}
При запуске приложения и загрузки страницы в консоль выдаёт следующие ошибки
template: index.html:4: unexpected define in command
template: index.html:4: unexpected define in command
runtime error: invalid memory address or nil pointer dereference
Подскажите, в чём может быть ошибка и правильно ли так делать в golang. Гуглил, но ничего толкового не нашёл.
Разобрался с ошибками. Заменил
{{ define "title" }}
Home
{{ end }}
на
{{ block "title" .}}
Home
{{end}}
Страницы открывается, всё работает.
Ответы (1 шт):
Нельзя использовать в одном файле два и более define, лучше только один. Define это связывание строковой константы и кода шаблона. Включение дефайнов друг в друга вызовет ошибку.
Отвечая на вопрос "как лучше делать", я бы посоветовал следующее:
1) использовать github.com/valyala/fasthttp вместо net/http. Данный пакет намного производительней
2) подумать над роутингом, я использую github.com/buaazp/fasthttprouter
3) организовать что-то вроде лайт MVC, когда каждый урл обрабатывается отдельной функцией, я лично использую в связке с fasthttp такую конструкцию
func RunController(controller func(ctx *fasthttp.RequestCtx)) func(ctx *fasthttp.RequestCtx) {
return func(ctx *fasthttp.RequestCtx) {
setDefaultHeaders(ctx)
controller(ctx)
}
}
функция выше принимает в качестве параметра другую функцию (контроллер), выполняет некий middleware код и выполняет уже сам контроллер.
а в связке с fasthttprouter это работает так
router.GET("/user", RunController(User))
func User(ctx *fasthttp.RequestCtx) {
//получаем некие данные
interactor := components.GetInteractor()
users, _ := interactor.UserRep.GetAll()
data := map[string]interface{}{
"users": users,
}
//рисуем наш Html
components.ExecuteTemplate(ctx, "user/user.html", data)
}
4) не парсить шаблоны при каждом вызове контроллера (функции Index в вашем случае)