Вложенные циклы в Go шаблонах - PullRequest
3 голосов
/ 28 мая 2020

кодеров. Мне нужно отобразить данные вложенной структуры в шаблоне go. Интересно, можно ли использовать вложенные циклы в файле шаблона .gohtml. Вот мой .gohtml код:

<!DOCTYPE html>
<html>
    <head>
        <meta charser="utf-8" />
        <title>Go templates</title>
    </head>
    <body>
        <ul>
            {{range $city := .}}
                <li>
                    name: {{$city.name}}
                    hotels:
                        <ul>
                            {{range $hotel := $city.hotels}}
                                <li>
                                    name: {{$hotel.name}}
                                    address: {{$hotel.address}}
                                    zip: {{$hotel.zip}}
                                </li>
                            {{end}}
                        </ul>
                </li>
            {{end}}
        </ul>
    </body>
</html>

Вот main.go код:

package main

import (
    "os"
    "text/template"
)

var tpl *template.Template

func init() {
    tpl = template.Must(template.New("").ParseGlob("./*.gohtml"))
}

func main() {
    type hotel struct {
        name    string
        address string
        city    string
        zip     int
    }
    type city struct {
        name   string
        hotels []hotel
    }
    type region struct {
        cities []city
    }

    hotel1 := hotel{
        "Lambda",
        "Street 19",
        "Some city",
        65530,
    }
    hotel2 := hotel{
        "Black Sea",
        "Street 21",
        "Some city",
        65543,
    }
    hotel3 := hotel{
        "Blue Sea",
        "Street 15",
        "Some city",
        54400,
    }
    hotel4 := hotel{
        "Yellow Submarine",
        "The Beatles Square",
        "Some city",
        54401,
    }
    hotel5 := hotel{
        "LolKek",
        "Cheburek",
        "Some city",
        14213,
    }

    city1 := city{
        "Some city",
        []hotel{hotel1, hotel2},
    }
    city2 := city{
        "Some city",
        []hotel{hotel3, hotel4},
    }
    city3 := city{
        "Some city",
        []hotel{hotel5},
    }

    someRegion := region{
        []city{city1, city2, city3},
    }

    tpl.ExecuteTemplate(os.Stdout, "tpl.gohtml", someRegion)
}

Нет ошибки в терминале, когда go run main.go, но я не поймите, почему вывод выглядит так:

<!DOCTYPE html>
<html>
        <head>
                <meta charser="utf-8" />
                <title>Go templates</title>
        </head>
        <body>
                <ul>

Почему вырезано?

1 Ответ

4 голосов
/ 28 мая 2020

Вы не видите никаких ошибок, потому что вы не проверяете ошибки, вы их пропускаете.

Template.ExecuteTemplate() возвращает ошибку, проверьте ее:

if err := tpl.ExecuteTemplate(os.Stdout, "tpl.gohtml", someRegion); err != nil {
    fmt.Println(err)
}

Это выведет:

template: :9:29: executing "" at <.>: range can't iterate over {[{Some city [{Lambda Street 19 Some city 65530} {Black Sea Street 21 Some city 65543}]} {Some city [{Blue Sea Street 15 Some city 54400} {Yellow Submarine The Beatles Square Some city 54401}]} {Some city [{LolKek Cheburek Some city 14213}]}]}

Ошибка очевидна: вы передаете структуру для выполнения, а затем пытаетесь перейти к ней. Вы не можете. Диапазон по срезу:

{{range $city := .cities}}

Это, конечно, не сработает: вам нужно экспортировать поле структуры, чтобы иметь доступ к нему внутри шаблона.

type region struct {
    Cities []city
}

И в шаблон:

{{range $city := .Cities}}

Вы также должны экспортировать другие поля структуры:

type hotel struct {
    Name    string
    Address string
    City    string
    Zip     int
}
type city struct {
    Name   string
    Hotels []hotel
}

После этих изменений он будет работать и выводить (попробуйте на Go Playground ):

<!DOCTYPE html>
<html>
    <head>
        <meta charser="utf-8" />
        <title>Go templates</title>
    </head>
    <body>
        <ul>

                <li>
                    name: Some city
                    hotels:
                        <ul>

                                <li>
                                    name: Lambda
                                    address: Street 19
                                    zip: 65530
                                </li>

                                <li>
                                    name: Black Sea
                                    address: Street 21
                                    zip: 65543
                                </li>

                        </ul>
                </li>

                <li>
                    name: Some city
                    hotels:
                        <ul>

                                <li>
                                    name: Blue Sea
                                    address: Street 15
                                    zip: 54400
                                </li>

                                <li>
                                    name: Yellow Submarine
                                    address: The Beatles Square
                                    zip: 54401
                                </li>

                        </ul>
                </li>

                <li>
                    name: Some city
                    hotels:
                        <ul>

                                <li>
                                    name: LolKek
                                    address: Cheburek
                                    zip: 14213
                                </li>

                        </ul>
                </li>

        </ul>
    </body>
</html>
...