Templates Golang模板是基于角色的视图的更好方法
我试图为基于角色的模板用例找到一种更好、更有效的方法 您有三个不同的角色和不同的内容,为了简化示例,侧边栏对每个角色都是相同的 代码和模板方法是非常重复的,必须有更好的方法来获得它。 我可以用一些“如果”的句子来加载不同的模板,但这太慢了。 如果我在模板中使用新的Templates Golang模板是基于角色的视图的更好方法,templates,go,Templates,Go,我试图为基于角色的模板用例找到一种更好、更有效的方法 您有三个不同的角色和不同的内容,为了简化示例,侧边栏对每个角色都是相同的 代码和模板方法是非常重复的,必须有更好的方法来获得它。 我可以用一些“如果”的句子来加载不同的模板,但这太慢了。 如果我在模板中使用新的{{block}操作,它只为每个内容保存一行。我知道这里有点不对劲,但我搞不懂 提前谢谢 package main import ( "html/template" "log" "os" ) const t
{{block}
操作,它只为每个内容保存一行。我知道这里有点不对劲,但我搞不懂
提前谢谢
package main
import (
"html/template"
"log"
"os"
)
const t = `
{{define "header"}}==Header=={{end}}
{{define "sidebar"}}==Side Bar=={{end}}
{{define "footer"}}==Footer=={{end}}
{{define "index-role1"}}Welcome Stuff for Role1{{end}}
{{define "index-role2"}}Welcome Stuff for Role2{{end}}
{{define "index-role3"}}Welcome Stuff for Role3{{end}}
{{define "content1-role1"}}Content 1 for Role1{{end}}
{{define "content1-role2"}}Content 1 for Role2{{end}}
{{define "content1-role3"}}Content 1 for Role3{{end}}
{{define "content2-role1"}}Content 2 for Role1{{end}}
{{define "content2-role2"}}Content 2 for Role2{{end}}
{{define "content2-role3"}}Content 2 for Role3{{end}}
{{define "display-role1-index"}} {{template "header" .}}{{template "sidebar" . }} {{template "index-role1" .}}{{template "footer" .}} {{end}}
{{define "display-role1-content1"}} {{template "header" .}}{{template "sidebar" . }} {{template "content1-role1" .}}{{template "footer" .}}{{end}}
{{define "display-role1-content2"}} {{template "header" .}}{{template "sidebar" . }} {{template "content2-role1" .}}{{template "footer" .}}{{end}}
{{define "display-role2-index"}} {{template "header" .}}{{template "sidebar" . }} {{template "index-role2" .}}{{template "footer" .}}{{end}}
{{define "display-role2-content1"}} {{template "header" .}}{{template "sidebar" . }} {{template "content1-role2" .}}{{template "footer" .}}{{end}}
{{define "display-role2-content2"}} {{template "header" .}}{{template "sidebar" . }} {{template "content2-role2" .}}{{template "footer" .}}{{end}}
{{define "display-role3-index"}} {{template "header" .}}{{template "sidebar" . }} {{template "index-role3" .}}{{template "footer" .}}{{end}}
{{define "display-role3-content1"}} {{template "header" .}}{{template "sidebar" . }} {{template "content1-role3" .}}{{template "footer" .}}{{end}}
{{define "display-role3-content2"}} {{template "header" .}}{{template "sidebar" . }} {{template "content2-role3" .}}{{template "footer" .}}{{end}}
`
var templates map[string]*template.Template
type User struct {
Login string
Role string
}
func init() {
if templates == nil {
templates = make(map[string]*template.Template)
}
//Templates for role1
templates["role1-index"] = template.Must(template.New("display-role1-index").Parse(t))
templates["role1-content1"] = template.Must(template.New("display-role1-content1").Parse(t))
templates["role1-content2"] = template.Must(template.New("display-role1-content2").Parse(t))
//Templates for role2
...
//Templates for role3
...
}
func main() {
loggedUser := User{Login: "Username1", Role: "role1"}
// ONLY FOR INDEX
switch loggedUser.Role {
case "role1":
err := templates["role1-index"].Execute(os.Stdout, nil)
if err != nil {
log.Println(err.Error())
}
case "role2":
err := templates["role2-index"].Execute(os.Stdout, nil)
if err != nil {
log.Println(err.Error())
}
case "role3":
err := templates["role3-index"].Execute(os.Stdout, nil)
if err != nil {
log.Println(err.Error())
}
}
...
//CODE FOR CONTENT1
...
//CODE FOR CONTENT2
...
}
编辑:
我在想如果那样能帮上忙
const t = `
{{define "header"}}==Header=={{end}}
{{define "sidebar"}}==Side Bar=={{end}}
{{define "footer"}}==Footer=={{end}}
{{define "display-base"}}
{{template "header" .}}
{{template "sidebar" . }}
{{block "content" .}}Welcome {{block "role"}}Role 1{{end}}{{end}}
{{template "footer" .}}
{{end}}`
在我的问题中,我试图简化一些事情来解释我头脑中的想法,模板代码中的东西,比如“content1role1”,只是为了表明应该有一些html代码只用于Role1角色视图。
我在原始问题代码中添加了更多细节。简化代码
您的代码可以大大简化:
- 您只需要解析模板一次。您可以使用从其名称指定的集合中执行一个
- 模板名称很容易从角色名称派生(存储在
中),因此不需要任何开关user.role
索引
之外,还呈现content1
和content2
,但比您的要短得多:
const t = `...` // Your template source here
var templates = template.Must(template.New("all").Parse(t))
type User struct {
Login string
Role string
}
func main() {
u := User{Login: "Username1", Role: "role1"}
for _, name := range []string{"index", "content1", "content2"} {
templName := "display-" + u.Role + "-" + name
if err := templates.ExecuteTemplate(os.Stdout, templName, nil); err != nil {
log.Println(err.Error())
}
}
}
它输出:
==Header====Side Bar== Welcome Role1==Footer== ==Header====Side Bar==
Content 1 Role1==Footer== ==Header====Side Bar== Content 2 Role1==Footer==
如果将用户角色更改为role2
:
==Header====Side Bar== Welcome Role2==Footer== ==Header====Side Bar==
Content 1 Role2==Footer== ==Header====Side Bar== Content 2 Role2==Footer==
您可以创建一个helperrenderFor()
函数:
func renderFor(u User) {
for _, name := range []string{"index", "content1", "content2"} {
templName := "display-" + u.Role + "-" + name
if err := templates.ExecuteTemplate(os.Stdout, templName, nil); err != nil {
log.Println(err.Error())
}
}
}
并为多个用户调用它:
renderFor(User{Login: "Username1", Role: "role1"})
fmt.Println()
renderFor(User{Login: "Username2", Role: "role2"})
试穿一下
简化模板
简化模板的一种方法是不为单独的角色定义单独的模板,而是使用模板操作来呈现不同的内容和/或将不同的数据传递给要包含在输出中的执行(以产生不同的内容)。在执行模板时,必须传递角色和其他必需的信息,以便使用它来区分。例如,您的所有模板都可以替换为以下内容:
const t = `
{{define "header"}}==Header=={{end}}
{{define "sidebar"}}==Side Bar=={{end}}
{{define "footer"}}==Footer=={{end}}
{{define "index"}}Welcome {{.Role}}{{end}}
{{define "content1"}}Content 1 {{.Role}}{{end}}
{{define "content2"}}Content 2 {{.Role}}{{end}}
{{define "display-index"}} {{template "header" .}}{{template "sidebar" . }} {{template "index" .}}{{template "footer" .}} {{end}}
{{define "display-content1"}} {{template "header" .}}{{template "sidebar" . }} {{template "content1" .}}{{template "footer" .}}{{end}}
{{define "display-content2"}} {{template "header" .}}{{template "sidebar" . }} {{template "content2" .}}{{template "footer" .}}{{end}}
`
请注意,roleX
已从模板名称中删除,这就是重点
以及执行模板:
func renderFor(u User) {
for _, name := range []string{"index", "content1", "content2"} {
templName := "display-" + name
if err := templates.ExecuteTemplate(os.Stdout, templName, u); err != nil {
log.Println(err.Error())
}
}
}
请注意,用户u
被传递到ExecuteTemplate()
。试穿一下
您的示例可能太不现实,这就是为什么我们可以大幅减少它,但这也是在更复杂的示例中使用的方法
还请注意,根据设计理念,模板不应包含复杂的逻辑。如果在模板中有(或看起来)太复杂,则应该考虑在GO代码中计算结果,或者将结果作为数据传递给执行,或者在模板中登记回调函数,并具有模板动作调用,并插入返回值。
您的代码可以大大简化:
- 您只需要解析模板一次。您可以使用从其名称指定的集合中执行一个
- 模板名称很容易从角色名称派生(存储在
中),因此不需要任何开关user.role
索引
之外,还呈现content1
和content2
,但比您的要短得多:
const t = `...` // Your template source here
var templates = template.Must(template.New("all").Parse(t))
type User struct {
Login string
Role string
}
func main() {
u := User{Login: "Username1", Role: "role1"}
for _, name := range []string{"index", "content1", "content2"} {
templName := "display-" + u.Role + "-" + name
if err := templates.ExecuteTemplate(os.Stdout, templName, nil); err != nil {
log.Println(err.Error())
}
}
}
它输出:
==Header====Side Bar== Welcome Role1==Footer== ==Header====Side Bar==
Content 1 Role1==Footer== ==Header====Side Bar== Content 2 Role1==Footer==
如果将用户角色更改为role2
:
==Header====Side Bar== Welcome Role2==Footer== ==Header====Side Bar==
Content 1 Role2==Footer== ==Header====Side Bar== Content 2 Role2==Footer==
您可以创建一个helperrenderFor()
函数:
func renderFor(u User) {
for _, name := range []string{"index", "content1", "content2"} {
templName := "display-" + u.Role + "-" + name
if err := templates.ExecuteTemplate(os.Stdout, templName, nil); err != nil {
log.Println(err.Error())
}
}
}
并为多个用户调用它:
renderFor(User{Login: "Username1", Role: "role1"})
fmt.Println()
renderFor(User{Login: "Username2", Role: "role2"})
试穿一下
简化模板
简化模板的一种方法是不为单独的角色定义单独的模板,而是使用模板操作来呈现不同的内容和/或将不同的数据传递给要包含在输出中的执行(以产生不同的内容)。在执行模板时,必须传递角色和其他必需的信息,以便使用它来区分。例如,您的所有模板都可以替换为以下内容:
const t = `
{{define "header"}}==Header=={{end}}
{{define "sidebar"}}==Side Bar=={{end}}
{{define "footer"}}==Footer=={{end}}
{{define "index"}}Welcome {{.Role}}{{end}}
{{define "content1"}}Content 1 {{.Role}}{{end}}
{{define "content2"}}Content 2 {{.Role}}{{end}}
{{define "display-index"}} {{template "header" .}}{{template "sidebar" . }} {{template "index" .}}{{template "footer" .}} {{end}}
{{define "display-content1"}} {{template "header" .}}{{template "sidebar" . }} {{template "content1" .}}{{template "footer" .}}{{end}}
{{define "display-content2"}} {{template "header" .}}{{template "sidebar" . }} {{template "content2" .}}{{template "footer" .}}{{end}}
`
请注意,roleX
已从模板名称中删除,这就是重点
以及执行模板:
func renderFor(u User) {
for _, name := range []string{"index", "content1", "content2"} {
templName := "display-" + name
if err := templates.ExecuteTemplate(os.Stdout, templName, u); err != nil {
log.Println(err.Error())
}
}
}
请注意,用户u
被传递到ExecuteTemplate()
。试穿一下
您的示例可能太不现实,这就是为什么我们可以大幅减少它,但这也是在更复杂的示例中使用的方法
还请注意,根据设计理念,模板不应包含复杂的逻辑。如果模板中有一些(或看起来)太复杂,则应该考虑在GO代码中计算结果,或者将结果作为数据传递给执行,或者在模板中登记回调函数,并具有模板动作调用,并插入返回值。但是有没有一种方法可以简化类似用例模板中的逻辑?再次感谢@icza,也许我没有正确解释我的问题,我只是添加了更多关于它的信息。好的@icza感谢你的回答,但是有没有一种方法可以简化类似用例模板中的逻辑?再次感谢@icza,也许我没有正确解释我的问题,我只是补充了更多的信息。