web-dev-qa-db-ja.com

golang HTMLテンプレート内の切り替えまたはif / elseif / else

私はこの構造を持っています:

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に依存した方法で段落を表示したい。

私が見つけた唯一の解決策は、GoでisAttachmentとネストされた{{if}}をテストするTypeのような専用関数に基づいていました。

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

実際、私はさらに多くの型を持っているので、さらに奇妙になり、IsSomething関数を使用したGoコードと{{end}}を使用したテンプレートの両方が乱雑になります。

クリーンなソリューションは何ですか? goテンプレートにいくつかのswitchまたはif/elseif/elseソリューションがありますか?または、これらのケースを処理するためのまったく異なる方法ですか?

33
Denys Séguret

テンプレートにはロジックがありません。彼らはこの種の論理を持つべきではありません。最大のロジックは、ifの束です。

このような場合、次のようにする必要があります。

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

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

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

はい、{{else if .IsMenu}}を使用できます

12
mcfedr

template.FuncMap にカスタム関数を追加することにより、switch機能を実現できます。

以下の例では、printPara (paratype int) stringという関数を定義しました。これは、定義済みの段落タイプの1つを受け取り、それに応じて出力を変更します。

実際のテンプレートでは、.Paratypeprintpara関数にパイプされます。これは、テンプレートでパラメーターを渡す方法です。 FuncMapsに追加される関数の出力パラメーターの数と形式には制限があることに注意してください。 このページ には、最初のリンクだけでなく、いくつかの良い情報があります。

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

生産物:

これは仮説です

これは添付ファイルです

メニュー
1:
2:
3:

任意のオプションを選択:

プレイグラウンドリンク

これがお役に立てば幸いです。コードを少しクリーンアップできると確信していますが、提供されたサンプルコードに近づけるように努めました。

7
Intermernet