我只是接受,如果我的术语不准确,请道歉。我的最终目标是将缓存的CSS文件的名称添加到我的Go应用程序的布局模板中。应用程序启动时动态构建的CSS文件无法进行硬编码。在我的模板文件中,我有这个:
//More html here
<link href="{{.CSSFile}}" rel="stylesheet">
//more html here
我在View类型上有一个Render方法,如下所示。它需要data interface{}
作为参数,然后运行ExecuteTemplate
。它由每个控制器以这种或那种方式调用,它发送data
参数并公开信息。我知道如何将它作为来自控制器的数据添加,然后调用Render
方法,但我显然不希望在每个控制器动作中添加CSS文件,因此最有意义的是将其添加到Render函数一次,并将其添加到传递给ExecuteTemplate
的数据中。我的问题是如何将这些信息添加到已传递给Render
的数据中,然后将整个信息传递给ExecuteTemplate
。我下面的内容适用于CSS文件,但它显然不会传递给传递给原始data
参数的Render
。
type View struct {
Template *template.Template
Layout string
}
func (v *View) Render(w http.ResponseWriter, data interface{}) error {
d := Data{}
d.AddCSSFile()
w.Header().Set("Content-Type", "text/html")
err := v.Template.ExecuteTemplate(w, v.Layout, d)
if err != nil {
log.Println(err)
fmt.Fprintln(w, "<h1>Something went wrong. Please contact us at support")
}
return nil
}
type Data struct {
Alerts []Alert
Yield interface{}
CSSFile interface{}
}
func (d *Data) AddCSSFile() {
ss, _ := filepath.Glob("./assets/site-*.css")
fp := strings.Join(ss, "")
_, d.CSSFile = filepath.Split(fp)
}
我已经创造了一个要点,但并非完全完整,从我正在尝试做的事情中更加充实: https://gist.github.com/codelitt/549a68149add0482c6dc2514a46aa580
答案 0 :(得分:2)
我不确定我确切地理解您要问的是什么,但如果你想要的是将data interface{}
参数与d := Data{}
内的Render
值相结合,那么你可以做点什么像这样...
// ...
func (v *View) Render(w http.ResponseWriter, data interface{}) error {
p := Page{Data:data}
p.AddCSSFile()
w.Header().Set("Content-Type", "text/html")
err := v.Template.ExecuteTemplate(w, v.Layout, p)
if err != nil {
log.Println(err)
fmt.Fprintln(w, "<h1>Something went wrong. Please contact us at support")
}
return nil
}
type Page struct {
Alerts []Alert
Yield interface{}
CSSFile interface{}
Data interface{}
}
func (p *Page) AddCSSFile() {
// ...
}
修改或者您也可以初始化匿名结构值并将其传递给ExecuteTemplate
,而无需更改现有的Data
类型。
// ...
err := v.Template.ExecuteTemplate(w, v.Layout, struct{
Data
Args interface{}
}{Data:d, Args:data})
// ...
Edit2:因此,如果我正确理解您的评论,传递给data interface{}
方法的Render
参数可能在某些或所有实例中都是或包含一个类型的值匹配其中一个Data
字段&#39;类型,在这种情况下,您希望将该值设置为该字段,以便将它们一起传递给ExecuteTemplate
方法。正如您已经发现的那样,至少有一个解决方案是使用类型断言。以下是来自问题中原始示例的上下文中的注释的示例的略微修改版本。
func (v *View) Render(w http.ResponseWriter, data interface{}) error {
d := Data{}
d.AddCSSFile()
if alerts, ok := data.([]Alert); ok {
d.Alerts = alerts
}
w.Header().Set("Content-Type", "text/html")
err := v.Template.ExecuteTemplate(w, v.Layout, d)
if err != nil {
log.Println(err)
fmt.Fprintln(w, "<h1>Something went wrong. Please contact us at support")
}
return nil
}