Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Templates Golang模板是基于角色的视图的更好方法_Templates_Go - Fatal编程技术网

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==
您可以创建一个helper
renderFor()
函数:

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==
您可以创建一个helper
renderFor()
函数:

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,也许我没有正确解释我的问题,我只是补充了更多的信息。