英文:
Is it possible for a Golang template function to render another template while referring to itself?
问题
我想要扩展默认的Golang模板函数,添加一个模板函数,该函数可以渲染另一个Golang模板,并且该模板也应该能够访问该函数。
以下演示案例应该创建一个名为include
的模板函数,该函数可以渲染给定的模板,该模板也可以包含相同的include
函数。然而,这个例子(正确地)引发了一个初始化循环错误。
Golang模板函数是否可以在渲染另一个模板时引用自身?
package main
import (
"bytes"
"errors"
html_template "html/template"
"os"
)
var includeFuncs = map[string]interface{}{
"include": func(templatePath string, data interface{}) (string, error) {
templatePath = "templates/" + templatePath
if _, err := os.Stat(templatePath); err != nil {
return "", errors.New("Unable to find the template file " + templatePath)
}
var renderedTpl bytes.Buffer
tpl, err := html_template.New(templatePath).Funcs(GetHTMLIncludeFuncs()).Parse(templatePath)
if err != nil {
return "", err
}
if err := tpl.Execute(&renderedTpl, data); err != nil {
return "", err
}
return renderedTpl.String(), nil
},
}
func GetHTMLIncludeFuncs() html_template.FuncMap {
return html_template.FuncMap(includeFuncs)
}
英文:
I want to extend the default Golang template functions with a template function that renders another Golang template while that template also should have access to the function in question.
The following demonstration case should create an include
template function that renders a given template which could also include the same include
function. The example, however (rightfully) raises an initialization cycle error.
Is it possible for a Golang template function to render another template while referring to itself?
https://play.golang.org/p/hml-GDhV1HI
package main
import (
"bytes"
"errors"
html_template "html/template"
"os"
)
var includeFuncs = map[string]interface{}{
"include": func(templatePath string, data interface{}) (string, error) {
templatePath = "templates/" + templatePath
if _, err := os.Stat(templatePath); err != nil {
return "", errors.New("Unable to find the template file " + templatePath)
}
var renderedTpl bytes.Buffer
tpl, err := html_template.New(templatePath).Funcs(GetHTMLIncludeFuncs()).Parse(templatePath)
if err != nil {
return "", err
}
if err := tpl.Execute(&renderedTpl, data); err != nil {
return "", err
}
return renderedTpl.String(), nil
},
}
func GetHTMLIncludeFuncs() html_template.FuncMap {
return html_template.FuncMap(includeFuncs)
}
答案1
得分: 1
使用init()
:
var includeFuncs = map[string]interface{}{}
func includeFunc(templatePath string, data interface{}) (string, error) {...}
func init() {
includeFuncs["include"]=includeFunc
}
在原始帖子中,你陷入了一个初始化循环,因为在执行开始之前,运行时必须初始化所有已初始化的变量,而编译器检测到了初始化循环。
通过上述解决方案,初始化可以在程序开始之前完成,因为函数映射为空。在main
开始运行之前,init
函数运行并使用该函数初始化映射。
英文:
Use init()
:
var includeFuncs = map[string]interface{}{}
func includeFunc(templatePath string, data interface{}) (string, error) {...}
func init() {
includeFuncs["include"]=includeFunc
}
In the original post, you fall into an initialization loop because before the execution starts, the runtime has to initialize all initialized variables, and the compiler detects the initialization loop.
With the above solution, the initialization can complete before the program starts because the function map is empty. Before main
starts running, the init
function runs and initializes the map with the function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论