web-dev-qa-db-ja.com

式とインデックスを使用してテンプレートに移動します

eqindexと一緒に使用すると、Goテンプレートで予期しない結果が発生します。このコードを参照してください:

package main

import (
    "os"
    "text/template"
)

func main() {
    const myTemplate = `
{{range $n := .}}
    {{index $n 0}} {{if (index $n 0) eq (index $n 1)}}={{else}}!={{end}} {{index $n 1}}
{{end}}
`
    t := template.Must(template.New("").Parse(myTemplate))

    t.Execute(os.Stdout,
        [][2]int{
            [2]int{1, 2},
            [2]int{2, 2},
            [2]int{4, 2},
        })

}

私は出力を期待しています

1 != 2
2 = 2
4 != 2

しかし、私は得る

1 = 2
2 = 2
4 = 2

Goテンプレートの配列メンバーを比較できるようにするには何を変更する必要がありますか?

8
Ondra

eqはプレフィックス操作です:

{{if eq (index $n 0) (index $n 1)}}={{else}}!={{end}}

遊び場: http://play.golang.org/p/KEfXH6s7N1

8
Ainar-G

間違った演算子と引数の順序を使用しています。最初に演算子を記述し、次にオペランドを記述する必要があります。

{{if eq (index $n 0) (index $n 1)}}

eqは2つ以上の引数を取ることができるため、これはより読みやすく便利です。たとえば、次のように記述できます。

{{if eq (index $n 0) (index $n 1) (index $n 2)}}

より単純な多元等価性テストの場合、eq(のみ)は2つ以上の引数を受け入れ、2番目以降を比較して有効に戻ります。

arg1==arg2 || arg1==arg3 || arg1==arg4 ...

(ただし、Goの||とは異なり、eqは関数呼び出しであり、すべての引数が評価されます。)

これで出力を変更します( Go Playground で試してください):

1 != 2

2 = 2

4 != 2

注:

「ループ」変数を導入する必要はありません。{{range}}アクションはドットを現在のアイテムに変更します。

...ドットは、配列、スライス、またはマップの連続する要素に設定されます...

したがって、テンプレートを単純化できます。これは、テンプレートと同等です。

{{range .}}
    {{index . 0}} {{if eq (index . 0) (index . 1)}}={{else}}!={{end}} {{index . 1}}
{{end}}

また、テンプレートに変数を自分で作成できることにも注意してください。これは、同じ式を複数回使用する場合に推奨されますが、これは重要です(index . 0など)。これもテンプレートと同等です。

{{range .}}{{$0 := index . 0}}{{$1 := index . 1}}
    {{$0}} {{if eq $0 $1}}={{else}}!={{end}} {{$1}}
{{end}}

また、この特定のケースでは、ifブランチとelseブランチの両方に=記号が含まれているため、2つのブランチは必要ありません。=はで出力する必要があります。どちらの場合も、等しくない場合は、追加の!記号が必要です。したがって、次の最終的なテンプレートもあなたのものと同等です。

{{range .}}{{$0 := index . 0}}{{$1 := index . 1}}
    {{$0}} {{if ne $0 $1}}!{{end}}= {{$1}}
{{end}}
4
icza