在golang的HTML模板中使用switch或if/elseif/else语句

huangapple go评论93阅读模式
英文:

Switch or if/elseif/else inside golang HTML templates

问题

我有这个结构体:

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
}

我想以Type的方式显示我的段落。

我找到的唯一解决方案是基于专用函数(如isAttachment)在Go中测试Type和嵌套的{{if}}

{{range .Paragraphs}}
    {{if .IsAttachment}}
        -- 附件展示代码 --
    {{else}}{{if .IsMenu}}
        -- 菜单 --
    {{else}}
        -- 默认代码 --
    {{end}}{{end}}
{{end}}

实际上,我有更多的类型,这使得情况变得更加奇怪,使得Go代码和模板都变得混乱,需要使用IsSomething函数和{{end}}

有什么干净的解决方案吗?在Go模板中是否有switchif/elseif/else的解决方案?或者完全不同的处理这些情况的方式?

英文:

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.

The only solution I found was based on dedicated functions like isAttachment testing the Type in Go and nested {{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}}.

What's the clean solution ? Is there some switch or if/elseif/else solution in go templates ? Or a completely different way to handle these cases ?

答案1

得分: 61

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

英文:

Yes, you can use {{else if .IsMenu}}

答案2

得分: 53

模板是无逻辑的。它们不应该有这种类型的逻辑。你能有的最大逻辑是一堆 if

在这种情况下,你应该这样做:

{{if .IsAttachment}}
    -- 附件展示代码 --
{{end}}

{{if .IsMenu}}
    -- 菜单 --
{{end}}

{{if .IsDefault}}
    -- 默认代码 --
{{end}}
英文:

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.

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}}

答案3

得分: 12

你可以通过向template.FuncMap添加自定义函数来实现switch功能。

在下面的示例中,我定义了一个函数printPara(paratype int) string,它接受你定义的段落类型之一,并相应地更改输出。

请注意,在实际模板中,.Paratype被传递到printpara函数中。这是如何在模板中传递参数的方法。请注意,向FuncMap添加的函数的输出参数的数量和形式有一些限制。这个页面有一些很好的信息,以及第一个链接。

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" // 一个简单的测试模板

    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)
        }
    }
}

输出:

This is a hypothesis

This is an attachment

Menu
1:
2:
3:

Pick any option:

Playground链接

希望对你有所帮助,我相信代码可以进行一些简化,但我尽量保持接近你提供的示例代码。

英文:

You can achieve switch functionality by adding custom functions to the template.FuncMap.

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.

Please note that, in the actual template, the .Paratype is piped into the printpara function. 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 FuncMaps. This page has some good info, as well as the first link.

package main

import (
    &quot;fmt&quot;
    &quot;os&quot;
    &quot;html/template&quot;
)

func main() {

    const (
        paragraph_hypothesis = 1 &lt;&lt; iota
        paragraph_attachment = 1 &lt;&lt; iota
        paragraph_menu       = 1 &lt;&lt; iota
    )

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

    type Paragraph struct {
        Paratype int
    }

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

    t := template.New(&quot;testparagraphs&quot;)

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

    template.Must(t.Funcs(template.FuncMap{&quot;printpara&quot;: printPara}).Parse(text))

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

Produces:

>This is a hypothesis
>
>This is an attachment
>
>Menu
>1:
>2:
>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.

huangapple
  • 本文由 发表于 2013年6月7日 21:34:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/16985469.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定