Iterando através do mapa no modelo

91

Estou tentando exibir uma lista de aulas de ginástica (ioga, pilates etc.). Para cada tipo de aula, há várias aulas, então quero agrupar todas as aulas de Yoga, todas as aulas de Pilates e assim por diante.

Eu fiz esta função para pegar uma fatia e fazer um mapa dela

func groupClasses(classes []entities.Class) map[string][]entities.Class {
    classMap := make(map[string][]entities.Class)
    for _, class := range classes {
        classMap[class.ClassType.Name] = append(classMap[class.ClassType.Name], class)
    }
    return classMap
}

O problema agora é como posso iterar por ele, de acordo com http://golang.org/pkg/text/template/ , você precisa acessá-lo em .Keyformato, não sei as chaves (a menos que também tenha passado um slice de chaves no modelo). Como faço para desempacotar este mapa na minha visão.

Tudo o que tenho atualmente é

{{ . }} 

que exibe algo como:

map[Pilates:[{102 PILATES ~/mobifit/video/ocen.mpg 169 40 2014-05-03 23:12:12 +0000 UTC 2014-05-03 23:12:12 +0000 UTC 1899-12-30 00:00:00 +0000 UTC {PILATES Pilates 1 2014-01-22 21:46:16 +0000 UTC} {1 leebrooks0@gmail.com password SUPERADMIN Lee Brooks {Male true} {1990-07-11 00:00:00 +0000 UTC true} {1.85 true} {88 true} 2014-01-22 21:46:16 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false} {0001-01-01 00:00:00 +0000 UTC false} {0001-01-01 00:00:00 +0000 UTC false}} [{1 Mat 2014-01-22 21:46:16 +0000 UTC}]} {70 PILATES ~/mobifit/video/ocen.mpg 119 66 2014-03-31 15:12:12 +0000 UTC 2014-03-31 15:12:12 +0000 UTC 1899-12-30 00:00:00 +0000 UTC 
Lee
fonte

Respostas:

166

Verifique a seção Variáveis nos documentos do modelo Go. Um intervalo pode declarar duas variáveis, separadas por uma vírgula. O seguinte deve funcionar:

{{ range $key, $value := . }}
   <li><strong>{{ $key }}</strong>: {{ $value }}</li>
{{ end }}
Herman Schaaf
fonte
46

Como Herman apontou, você pode obter o índice e o elemento de cada iteração.

{{range $index, $element := .}}{{$index}}
{{range $element}}{{.Value}}
{{end}}
{{end}}

Exemplo de trabalho:

package main

import (
    "html/template"
    "os"
)

type EntetiesClass struct {
    Name string
    Value int32
}

// In the template, we use rangeStruct to turn our struct values
// into a slice we can iterate over
var htmlTemplate = `{{range $index, $element := .}}{{$index}}
{{range $element}}{{.Value}}
{{end}}
{{end}}`

func main() {
    data := map[string][]EntetiesClass{
        "Yoga": {{"Yoga", 15}, {"Yoga", 51}},
        "Pilates": {{"Pilates", 3}, {"Pilates", 6}, {"Pilates", 9}},
    }

    t := template.New("t")
    t, err := t.Parse(htmlTemplate)
    if err != nil {
        panic(err)
    }

    err = t.Execute(os.Stdout, data)
    if err != nil {
        panic(err)
    }

}

Resultado:

Pilates
3
6
9

Yoga
15
51

Playground: http://play.golang.org/p/4ISxcFKG7v

ANisus
fonte
Olá @ANisus, tenho um requisito de gerar json através de um modelo como abaixo, mas também tem vírgulas extras como na matriz de endereços no exemplo dado Output `` `{" name ":" Mus "," adresses ": [{" address ":" A "}, {" address ":" B "},]}` `` Exemplo de link do código play.golang.org/p/nD08y0noPHv
Mohammad Mustaqeem
1
@MohammadMustaqeem Você pode verificar o índice de cada iteração, e não adicionar uma vírgula na primeira iteração. Veja o exemplo: play.golang.org/p/5544hc_0_g8 . Apenas tenha cuidado. Renderizar JSON com modelos causará problemas de escape. Veja o endereço "C&D" que adicionei.
ANisus
obrigado. Resolvi o problema de escape importando "text / template" em vez de "html / template". play.golang.org/p/PXTNZGWx7Yi
Mohammad Mustaqeem
1
@MohammadMustaqeem Infelizmente, agora você pode obter JSON inválido ou, pior ainda, JSON injetado: play.golang.org/p/kd9bM_rpwyg . Usar o template para gerar json não é aconselhável, mas se for necessário, escape os valores JSON com funções como js (também neste exemplo).
ANisus