英文:
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模板中是否有switch
或if/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:
希望对你有所帮助,我相信代码可以进行一些简化,但我尽量保持接近你提供的示例代码。
英文:
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 FuncMap
s. 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:
>2:
>3:
>
>Pick any option:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论