web-dev-qa-db-fra.com

Changer ou si / elseif / else à l'intérieur des modèles HTML de Golang

J'ai cette structure:

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
}

Je souhaite afficher mes paragraphes de manière dépendante de Type.

La seule solution que j'ai trouvée était basée sur des fonctions dédiées comme isAttachment tester le Type dans Go et imbriqué {{if}}:

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

En fait, j'ai plus de types, ce qui le rend encore plus étrange, encombrant à la fois le code Go avec les fonctions IsSomething et le modèle avec ces {{end}}.

Quelle est la solution propre? Y a-t-il switch ou if/elseif/else solution dans les modèles go? Ou une manière complètement différente de gérer ces cas?

33
Denys Séguret

Les modèles sont sans logique. Ils ne sont pas censés avoir ce genre de logique. La logique maximale que vous pouvez avoir est un tas de if.

Dans un tel cas, vous êtes censé le faire comme ceci:

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

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

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

Oui, vous pouvez utiliser {{else if .IsMenu}}

12
mcfedr

Vous pouvez obtenir la fonctionnalité switch en ajoutant des fonctions personnalisées à template.FuncMap .

Dans l'exemple ci-dessous, j'ai défini une fonction, printPara (paratype int) string qui prend l'un de vos types de paragraphe définis et modifie sa sortie en conséquence.

Veuillez noter que, dans le modèle actuel, le .Paratype est canalisé dans la fonction printpara. Voici comment passer des paramètres dans les modèles. Veuillez noter qu'il existe des restrictions sur le nombre et la forme des paramètres de sortie pour les fonctions ajoutées aux FuncMaps. Cette page a quelques bonnes informations, ainsi que le premier lien.

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

Produit:

Ceci est une hypothèse

Ceci est une pièce jointe

Menu
1:
2:
3:

Choisissez n'importe quelle option:

Lien Playground

J'espère que cela aide, je suis presque sûr que le code pourrait être nettoyé un peu, mais j'ai essayé de rester proche de l'exemple de code que vous avez fourni.

7
Intermernet