Go - html/template、template.ParseGlob() 和代码重用

标签 go go-html-template

我正在尝试在 Go 中使用 html/template 嵌入模板。我非常喜欢无逻辑模板设计,并且我相信它能够按预期安全地转义(有时其他模板库会出错)。

但是,我在尝试实现一个小助手以根据“最终”模板名称在我的 HTTP 处理程序中呈现我的模板时遇到了一些问题。我的 base.tmpl 在我的所有页面上都是有效的“标准”,如果不是,我可以在 base.tmpl 中设置 {{ template checkoutJS }} 并添加一些每页 JS通过设置 {{ define checkoutJS }}https://path.to/extra.js {{ end }}

我希望能够在我的 HTTP 处理程序中使用 renderTemplate(w, "template_name.tmpl", data),其中 data 是一个 map[string] 接口(interface){} 包含字符串或结构以及我希望填写的任何内容。

这是目前的代码:

base.tmpl

{{ define "base" }}
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ template "title" . }}</title>
</head>
<body>
<div id="sidebar">
...
</div>

{{ template "content" }}

<div id="footer">
...
</div>
</body>
</html>

create_listing.tmpl

{{ define "title" }}Create a New Listing{{ end }}

{{ define "content" }}

<form>
  ...
</form>

{{ end }}

login_form.tmpl

{{ define "title" }}Login{{ end }}

{{ define "content" }}

<form>
  ...
</form>

{{ end }}

ma​​in.go

package main

import (
  "fmt"
    "github.com/gorilla/mux"
    "html/template"
    "log"
    "net/http"
)

// Template handling shortcuts
var t = template.New("base")

func renderTemplate(w http.ResponseWriter, tmpl string, data map[string]interface{}) {

    err := t.ExecuteTemplate(w, tmpl, data)

  // Things will be more elegant than this: just a placeholder for now!
    if err != nil {
        http.Error(w, "error 500:"+" "+err.Error(), http.StatusInternalServerError)
    }
}

func monitorLoginForm(w http.ResponseWriter, r *http.Request) {

    // Capture forms, etc.

    renderTemplate(w, "login_form.tmpl", nil)
}

func createListingForm(w http.ResponseWriter, r *http.Request) {

    // Grab session, re-populate form if need be, generate CSRF token, etc

    renderTemplate(w, "create_listing.tmpl", nil)
}

func main() {

    r := mux.NewRouter()

    r.HandleFunc("/monitor/login", monitorLoginForm)

    http.Handle("/", r)
    log.Fatal(http.ListenAndServe(":8000", nil))

}

func init() {

    fmt.Println("Starting up.")
    _, err := t.ParseGlob("templates/*.tmpl")
    if err != nil {
        log.Fatal("Error loading templates:" + err.Error())
    }
}

这会编译,但我从我的处理程序那里得到一个空的响应。请注意,我没有第二个处理程序的路由:该代码只是为了显示我想如何从处理程序调用 renderTemplate()

最佳答案

你不能用当前的 go 模板包做你想做的事。模板没有继承,因此也没有模板中的命名 block 。定义页眉和页脚模板更常见,而不是定义基本模板。然后,在您的页面模板中,明确包含您希望它们所在的位置。

我认为,另一种解决方案是采用两阶段模板阶段。第一个是为基本模板的所有 block 编译模板。这些被添加到 map 中,然后发送到基本模板以供包含。

关于Go - html/template、template.ParseGlob() 和代码重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19373586/

相关文章:

data-structures - golang - 无法找到定向多图包

go - 在 Go 中交叉编译 pkg 导入

go - 为什么传递的变量不呈现在html/template中?

hugo - 按用户定义的属性排序

go - 匿名结构作为模板中的管道

html - 如何在golang html/template中创建一个全局变量并在多个地方进行更改?

templates - 在 go html 模板中创建循环的最佳方法是什么?

ssl - 使用 golang mutual TLS auth 信任特定客户端

google-app-engine - 应用程序引擎在go中读取本地文件

macos - 在 OSX 10.9 上编译 C 包