简体   繁体   English

在golang HTML模板中切换或if / elseif / else

[英]Switch or if/elseif/else inside golang HTML templates

I have this struct : 我有这个结构:

const (
    paragraph_hypothesis = 1<<iota
    paragraph_attachment = 1<<iota
    paragraph_menu       = 1<<iota
)

type Paragraph struct {
    Type int // paragraph_hypothesis or paragraph_attachment or paragraph_menu
}

I want to display my paragraphs in a Type dependent way. 我想以Type相关的方式显示我的段落。

The only solution I found was based on dedicated functions like isAttachment testing the Type in Go and nested {{if}} : 我发现的唯一的解决方案是基于专用功能,如isAttachment测试Type在围棋和嵌套{{if}}

{{range .Paragraphs}}
    {{if .IsAttachment}}
        -- attachement presentation code  --
    {{else}}{{if .IsMenu}}
        -- menu --
    {{else}}
        -- default code --
    {{end}}{{end}}
{{end}}

In fact I have more types, which makes it even weirder, cluttering both the Go code with IsSomething functions and the template with those {{end}} . 事实上,我有更多的类型,这使得它甚至更奇怪,使用IsSomething函数和带有{{end}}的模板混乱。

What's the clean solution ? 什么是干净的解决方案? Is there some switch or if/elseif/else solution in go templates ? go模板中是否有一些switchif/elseif/else解决方案? Or a completely different way to handle these cases ? 还是以完全不同的方式处理这些案件?

Templates are logic-less. 模板是无逻辑的。 They're not supposed to have this kind of logic. 他们不应该有这种逻辑。 The maximum logic you can have is a bunch of if . 你可以拥有的最大逻辑是一堆if

In such a case, you're supposed to do it like this: 在这种情况下,你应该这样做:

{{if .IsAttachment}}
    -- attachment presentation code --
{{end}}

{{if .IsMenu}}
    -- menu --
{{end}}

{{if .IsDefault}}
    -- default code --
{{end}}

是的,您可以使用{{else if .IsMenu}}

You can achieve switch functionality by adding custom functions to the template.FuncMap . 您可以通过向template.FuncMap添加自定义函数来实现switch功能。

In the example below I've defined a function, printPara (paratype int) string which takes one of your defined paragraph types and changes it's output accordingly. 在下面的示例中,我定义了一个函数printPara (paratype int) string ,它接受一个已定义的段落类型并相应地更改其输出。

Please note that, in the actual template, the .Paratype is piped into the printpara function. 请注意,在实际模板中, .Paratype通过管道传输到printpara函数中。 This is how to pass parameters in templates. 这是如何在模板中传递参数。 Please note that there are restrictions on the number and form of the output parameters for functions added to FuncMap s. 请注意,添加到FuncMap的函数的输出参数的数量和形式有限制。 This page has some good info, as well as the first link. 这个页面有一些很好的信息,以及第一个链接。

package main

import (
    "fmt"
    "os"
    "html/template"
)

func main() {

    const (
        paragraph_hypothesis = 1 << iota
        paragraph_attachment = 1 << iota
        paragraph_menu       = 1 << iota
    )

    const text = "{{.Paratype | printpara}}\n" // A simple test template

    type Paragraph struct {
        Paratype int
    }

    var paralist = []*Paragraph{
        &Paragraph{paragraph_hypothesis},
        &Paragraph{paragraph_attachment},
        &Paragraph{paragraph_menu},
    }

    t := template.New("testparagraphs")

    printPara := func(paratype int) string {
        text := ""
        switch paratype {
        case paragraph_hypothesis:
            text = "This is a hypothesis\n"
        case paragraph_attachment:
            text = "This is an attachment\n"
        case paragraph_menu:
            text = "Menu\n1:\n2:\n3:\n\nPick any option:\n"
        }
        return text
    }

    template.Must(t.Funcs(template.FuncMap{"printpara": printPara}).Parse(text))

    for _, p := range paralist {
        err := t.Execute(os.Stdout, p)
        if err != nil {
            fmt.Println("executing template:", err)
        }
    }
}

Produces: 生产:

This is a hypothesis 这是一个假设

This is an attachment 这是一个附件

Menu 菜单
1: 1:
2: 2:
3: 3:

Pick any option: 选择任何选项:

Playground link 游乐场链接

Hope that helps, I'm pretty sure the code could be cleaned up a bit, but I've tried to stay close to the example code you provided. 希望有所帮助,我很确定代码可以清理一下,但我试图接近你提供的示例代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM