应用程序启动后是否可以重新加载html模板?

Dat*_*sik 4 go

现在我正在将所有模板解析为变量,如下所示:

var templates = template.New("Template")

func LoadTemplates() {
    filepath.Walk("view/", func(path string, info os.FileInfo, err error) error {
        if strings.HasSuffix(path, ".html") {
            templates.ParseFiles(path)
        }
        return nil
    })
}

func Render(w http.ResponseWriter, tmplName string, data interface{}) {
    if err := templates.ExecuteTemplate(w, tmplName, data); err != nil {
        log.Println(err)
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,如果我进行任何更改,我需要重新启动整个应用程序.我有什么方法可以做到这一点,以便在制作时反映出变化

fl0*_*cke 9

在开发/处于调试模式时,完全可以在每个请求上重新加载模板.

您可以像这样定义一个接口和两个"模板执行器"

type TemplateExecutor interface{
    ExecuteTemplate(wr io.Writer, name string, data interface{}) error
}

type DebugTemplateExecutor struct  {
    Glob string
}

func (e DebugTemplateExecutor) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
    t := template.Must(template.ParseGlob(e.Glob))
    return t.ExecuteTemplate(wr, name, data)
}

type ReleaseTemplateExecutor struct  {
    Template *template.Template
}

func (e ReleaseTemplateExecutor) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
    return e.Template.ExecuteTemplate(wr, name, data)
}
Run Code Online (Sandbox Code Playgroud)

包装template.Execute().在运行时选择你想要的那个,例如

const templateGlob = "templates/*.html"
const debug = true

var executor TemplateExecutor

func main() {
    if debug {
        executor = DebugTemplateExecutor{templateGlob}

    } else {
        executor = ReleaseTemplateExecutor{
            template.Must(template.ParseGlob(templateGlob)),
        }
    }

    http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        executor.ExecuteTemplate(w, "test.html", nil)
    })

    http.ListenAndServe(":3000", nil)
}
Run Code Online (Sandbox Code Playgroud)

如果您需要在生产中进行热重新加载,我建议您查看目录以进行更改,而不是在每次请求时编译它.


And*_*och 2

是的,可以在运行时重新加载(html 或文本)模板。

只要应用程序可以访问您从中读取模板的文件夹,您就可以简单地重复模板解析。

你可以这样做:

var templates = template.New("Template")

func folderChanged(folder string) bool {
    // todo: implement filesystem watcher here
    return true
}

func ReloadTemplates(templateFolder string) {

    newTemplates, err := LoadTemplates(templateFolder)
    if err != nil {
        log.Println("Unable to load templates: %s", err)
        return
    }

    // override existing templates variable
    templates = newTemplates
}

func LoadTemplates(folder string) (*template.Template, error) {
    template := template.New("Template")

    walkError := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
        if strings.HasSuffix(path, ".html") {
            _, parseError := template.ParseFiles(path)
            if parseError != nil {
                return parseError
            }

        }

        return nil

    })

    return template, walkError
}

func Render(w http.ResponseWriter, tmplName string, data interface{}) {
    templateFolder := "view"
    if folderChanged(templateFolder) {
        ReloadTemplates(templateFolder)
    }

    if err := templates.ExecuteTemplate(w, tmplName, data); err != nil {
        log.Println(err)
    }

}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是示例中的 -folder 这样的相对路径,./view则仅当您执行应用程序的目录具有此类子文件夹时,它才有效。如果不是这种情况,我建议使用相对于用户主目录的路径或类似的路径。