Доступ к вложенным полям через рефлексию

Я использую шаблоны, и стоит задача получить динамические данные, при этом не добавляя в родительскую структуру дополнительные поля.

К примеру, у меня инстанцируется конфиг 1 раз, и соответственно я могу написать функцию, которая будет брать оттуда данные, напрямую не добавляю структуру конфига Config к примеру в структуру PasswordReset.

Но, дочерних структур в конфиге у меня много, поэтому мне нужно напрямую вызывать что-то на подобие App.BaseURL

type Config struct {
  App App
}

type App struct {
  BaseURL string 
}

fsTemplate, err := template.New(name).Funcs(template.FuncMap{
    "config": func(fieldName string) interface{} {
        f := reflect.Indirect(reflect.ValueOf(cfg)).FieldByName(fieldName).Interface()
        return f
    },
}

Но так не сработает, я не смогу взять данные из вложенной структуры

{{define "content"}}
BaseURL: {{.config "App.BaseURL"}}
{{end}}

Как я могу это сделать?


Ответы (1 шт):

Автор решения: Pak Uula

Зачем вы используете Funcs? Базовая нотация шаблонов вполне себе работает с многоуровневыми структурами: BaseURL: {{.App.BaseURL}}

Вот пример:

package main

import (
    "os"
    "text/template"
)

type Config struct {
    App App
}

type App struct {
    BaseURL string
}

func main() {
    cfg := Config{
        App: App{
            BaseURL: "http://example.com",
        },
    }
    fsTemplate, err := template.New("example").Parse(`
# Field inside field
BaseURL: {{.App.BaseURL}}`)

    if err != nil {
        panic(err)
    }

    err = fsTemplate.Execute(os.Stdout, cfg)
    if err != nil {
        panic(err)
    }
}

Результат:

# Field inside field
BaseURL: http://example.com
→ Ссылка