gpt4 book ai didi

go - 优化 html/模板组合

转载 作者:IT老高 更新时间:2023-10-28 13:09:19 25 4
gpt4 key购买 nike

我正在寻找是否有更好(更快、更有条理)的方式来拆分我在 Go 中的模板。我非常喜欢坚持使用 html/template(或其包装器),因为我信任它的安全模型。

  • 现在我使用 template.ParseGlob 来解析 init() 中的所有模板文件。
  • 我将 template.Funcs 应用于生成的模板
  • 我在每个模板中设置了一个 $title(即 listing_payment.tmpl)并将其传递给内容模板。
  • 我了解 html/template 模板解析后会缓存在内存中
  • 我的处理程序只调用 t.ExecuteTemplate(w, "name.tmpl", map[string]interface{}) 并且不对每个请求进行任何愚蠢的解析。
  • 我从多个部分组成模板(这是我觉得笨重的一点),如下所示:

    {{ $title := "Page Title" }}
    {{ template "head" $title }}
    {{ template "checkout" }}
    {{ template "top" }}
    {{ template "sidebar_details" . }}
    {{ template "sidebar_payments" }}
    {{ template "sidebar_bottom" }}

    <div class="bordered-content">
    ...
    {{ template "listing_content" . }}
    ...
    </div>

    {{ template "footer"}}
    {{ template "bottom" }}

我的三个问题是:

  1. 这是高效的,还是多个 {{ template "name"}} 标签会导致潜在的每个请求的性能下降?在对较重的页面进行压力测试时,我看到很多 write - broken pipe 错误。这可能只是由于套接字超时(即在编写器完成之前关闭套接字)而不是某种按请求组合,但是(如果不是,请纠正我!)

  2. 在 html/template 包的约束下,有没有更好的方法来做到这一点? Django's template docs 中的第一个示例接近我想要的。扩展基本布局并根据需要替换标题、侧边栏和内容 block 。

  3. 有点切题:当 template.ExecuteTemplate 在请求期间返回错误时,是否有惯用的方法来处理它?如果我将编写器传递给错误处理程序,我最终会在页面上看到汤(因为它只是继续写入),但重定向似乎不像惯用的 HTTP。

最佳答案

在 Reddit 上的一些帮助下,我设法找到了一种相当明智(和高效)的方法,它允许:

  • 使用内容 block 构建布局
  • 创建有效“扩展”这些布局的模板
  • 使用其他模板填充 block (脚本、侧边栏等)

base.tmpl

<html>
<head>
{{ template "title" .}}
</head>
<body>
{{ template "scripts" . }}
{{ template "sidebar" . }}
{{ template "content" . }}
<footer>
...
</footer>
</body>

index.tmpl

{{ define "title"}}<title>Index Page</title>{{ end }}
// We must define every block in the base layout.
{{ define "scripts" }} {{ end }}
{{ define "sidebar" }}
// We have a two part sidebar that changes depending on the page
{{ template "sidebar_index" }}
{{ template "sidebar_base" }}
{{ end }}
{{ define "content" }}
{{ template "listings_table" . }}
{{ end }}

... 和我们的 Go 代码,它利用了概述 in this SO answermap[string]*template.Template 方法:

var templates map[string]*template.Template

var ErrTemplateDoesNotExist = errors.New("The template does not exist.")

// Load templates on program initialisation
func init() {
if templates == nil {
templates = make(map[string]*template.Template)
}

templates["index.html"] = template.Must(template.ParseFiles("index.tmpl", "sidebar_index.tmpl", "sidebar_base.tmpl", "listings_table.tmpl", "base.tmpl"))
...
}

// renderTemplate is a wrapper around template.ExecuteTemplate.
func renderTemplate(w http.ResponseWriter, name string, data map[string]interface{}) error {
// Ensure the template exists in the map.
tmpl, ok := templates[name]
if !ok {
return ErrTemplateDoesNotExist
}

w.Header().Set("Content-Type", "text/html; charset=utf-8")
tmpl.ExecuteTemplate(w, "base", data)

return nil
}

从最初的基准测试(使用 wrk)来看,当涉及到重负载时,它的性能似乎要好一些,这可能是因为我们没有传递整个 ParseGlob 每个请求的模板值(value)。它还使创作模板本身变得更加简单。

关于go - 优化 html/模板组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24093923/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com