我有这个结构:
1 2 3 4 5 6 7 8 9 | 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 } |
我想以
我发现的唯一解决方案是基于专用功能,例如
1 2 3 4 5 6 7 8 9 | {{range .Paragraphs}} {{if .IsAttachment}} -- attachement presentation code -- {{else}}{{if .IsMenu}} -- menu -- {{else}} -- default code -- {{end}}{{end}} {{end}} |
实际上,我有更多的类型,这使其变得更加奇怪,使用
什么是干净的解决方案? Go模板中是否存在某些
-
您是指html模板吗? 您的
Paragraph 类型示例不太清楚。 通常,您可以通过向FuncMap(golang.org/pkg/text/template/#Template.Funcs)添加功能来创建自定义模板行为。 抱歉,我不确定您要做什么。
模板是无逻辑的。他们不应该具有这种逻辑。您可以拥有的最大逻辑是一堆
在这种情况下,您应该这样做:
1 2 3 4 5 6 7 8 9 10 11 | {{if .IsAttachment}} -- attachment presentation code -- {{end}} {{if .IsMenu}} -- menu -- {{end}} {{if .IsDefault}} -- default code -- {{end}} |
-
除了添加
isSomeValue 函数,没有其他方法可以测试Type 吗? - @dystroy很好,重点是将逻辑移出模板。所以,是的,您应该具有辅助功能。每当您使用无逻辑模板时,您就必须在其他技术中执行相同的操作。
-
实际上,问题始于
IsDefault 的定义。最后,从复制必须在模板和Go代码中都必须存在的所有表示逻辑开始,最后在Go中以冗长的冗长代码来支持模板,并且模板没有带来任何附加价值。 - 这太严格了吗?...需要针对字符串求值的条件是什么? @FlorianMargaine
- 替换:"文本/模板不应该具有这种逻辑。"带有:"文本/模板不支持更复杂的逻辑。"
-
有
else 和else if -
文本/模板包为复杂的逻辑提供了辅助功能。如果
{{else if .IsMenu}} 不够用,您可以执行类似{{if and .IsMenu (not .IsAttachment)}} 的操作。
是的,您可以使用
- 这可行。 也许这是模板的新功能。 谢谢
您可以通过将自定义功能添加到template.FuncMap中来实现
在下面的示例中,我定义了一个函数
请注意,在实际模板中,将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | 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}}\ " // 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\ " case paragraph_attachment: text ="This is an attachment\ " case paragraph_menu: text ="Menu\ 1:\ 2:\ 3:\ \ Pick any option:\ " } 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:
游乐场链接
希望能有所帮助,我很确定可以对代码进行一些整理,但我尝试与您提供的示例代码保持紧密联系。
-
这很有趣,但是在您的解决方案中,HTML段落的呈现是在Go(在
printPara 中)完成的。然后,使用模板似乎没有任何意义。 -
印刷仅是示范。您可以在
case 语句中插入任何代码,而不仅仅是自定义输出。您可以处理变量,更改结构值等。这实际上只是为了演示如何在模板中生成类似switch 的功能。 -
@Intermernet,但是您在那里没有在模板中生成任何
switch 之类的功能。我想我也想有一个更好的例子。 -
抱歉,我仍然不确定您要实现的目标,golang.org/pkg/text/template具有go native模板的所有功能。除了那里列出的内置功能之外,向FuncMap添加功能是我知道的修改输出的唯一方法。 @FlorianMargaine,该函数接受单个整数(菜单可能类似于菜单的
{{4 | printpara}} ),并且在内部通过对该整数执行switch语句来更改其行为。就像我可以在模板中模拟的那样,那与本地golangswitch 差不多。 - @Intermernet我认为自己和我都在寻找这样的东西:pastebin.com/QSz0vAxk
- 那正是我一直在寻找的东西。
-
@FlorianMargaine和@dystroy,驱动模板的数据是否来自结构?可能是类似
type Paragraph struct{Paratype int, Text string} 的东西吗? - @Intermernet是的,我删除了该结构的其他字段以使其更简单(并且在我当时那明显的错误观点中,使它更清楚)。
-
@dystroy,好吧,我想我可以重构该函数以使其接近您想要的功能。这是一个有趣的挑战,Ive甚至正在阅读源代码,以尝试确定
if 语句在模板中的工作方式。尽管not ,and 和or 如此,但if 并不是内置模板功能之一。希望我很快就会有事情:-) -
好的,经过大量阅读之后,似乎Id需要修改标准库(特别是对于初学者来说,尤其是golang.org/pkg/text/template/parse/#NodeType)才能实现真正的switch语句。 接下来最好的事情是一系列
{{if switch .Type | case 1}}...{{end}} (在FuncMap中定义自定义的Switch() 和Case() 函数),此时,您也可以只使用标准的if语句。 嗯,最近一小时左右,我就对词法分析器和解析器学到了很多东西! 如果您感兴趣的话,相关的资源在golang.org/src/pkg/text/template/parse。