it-swarm.com.de

Wechseln Sie oder if / elseif / else in Golang-HTML-Vorlagen

Ich habe diese Struktur:

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
}

Ich möchte meine Absätze Type abhängig anzeigen.

Die einzige Lösung, die ich gefunden habe, basierte auf dedizierten Funktionen wie isAttachment, die Type in Go testeten und {{if}} Verschachtelten:

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

Tatsächlich habe ich mehr Typen, was es noch seltsamer macht und sowohl den Go-Code mit IsSomething -Funktionen als auch die Vorlage mit diesen {{end}} Überfüllt.

Was ist die saubere Lösung? Gibt es eine switch oder if/elseif/else - Lösung in go-Vorlagen? Oder eine ganz andere Art, mit diesen Fällen umzugehen?

33
Denys Séguret

Vorlagen sind logiklos. Sie sollten diese Art von Logik nicht haben. Die maximale Logik, die Sie haben können, ist eine Menge von if.

In solch einem Fall solltest du es so machen:

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

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

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

Ja, Sie können {{else if .IsMenu}}

12
mcfedr

Sie können die switch -Funktionalität erreichen, indem Sie der template.FuncMap benutzerdefinierte Funktionen hinzufügen.

Im folgenden Beispiel habe ich eine Funktion definiert, printPara (paratype int) string, die einen Ihrer definierten Absatztypen übernimmt und die Ausgabe entsprechend ändert.

Bitte beachten Sie, dass in der eigentlichen Vorlage das .Paratype wird in die Funktion printpara weitergeleitet. So übergeben Sie Parameter in Vorlagen. Beachten Sie, dass die Anzahl und Form der Ausgabeparameter für Funktionen, die zu FuncMaps hinzugefügt werden, Einschränkungen unterliegen. Diese Seite hat einige gute Infos sowie den ersten 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)
        }
    }
}

Produziert:

Dies ist eine Hypothese

Dies ist ein Anhang

Speisekarte
1:
2:
3:

Wähle eine Option:

Link zum Spielplatz

Ich hoffe, das hilft, ich bin mir ziemlich sicher, dass der Code ein wenig aufgeräumt werden könnte, aber ich habe versucht, mich an den von Ihnen bereitgestellten Beispielcode zu halten.

7
Intermernet