Шаблон HTML, хранящийся в карте, аварийно завершает работу при первом вызове

Я использую приведенную ниже функцию для анализа и сохранения шаблона Go на карту при первом вызове шаблона.

Впоследствии шаблон загружается с карты для оптимизации.

// Resource ...
type Resource struct {
    Templates map[string]template.Template
}

func (res *Resource) FetchTemplate(templateName string) (template.Template, bool) {
    tmpl, ok := res.Templates[templateName]
    return tmpl, ok
}

func (res *Resource) ExecTemplate(w http.ResponseWriter, name, path string, model interface{}) error {
    t, ok := res.FetchTemplate(name)
    if !ok{
        t := template.New(name)
        t, err := t.ParseFiles(res.Assets + path)

        t = template.Must(t, err)

        if err != nil {
            return err
        }

        res.Templates[name] = *t
    }

    if err := t.Execute(w, model); err != nil {
        w.WriteHeader(http.StatusBadGateway)
        return err
    }

    return nil
}

Однако при первом вызове кода для шаблона он вызывает панику при вызове t.Execute.

Это всегда срабатывает впоследствии.

Вот журналы ошибок.

  /usr/local/go/src/net/http/server.go:1746 +0xd0
panic(0x15b3ac0, 0x1b1c8d0)
        /usr/local/go/src/runtime/panic.go:513 +0x1b9
html/template.(*Template).escape(0xc000127088, 0x0, 0x0)
        /usr/local/go/src/html/template/template.go:95 +0x32
html/template.(*Template).Execute(0xc000127088, 0x4a90200, 0xc000374680, 0x15ed6c0, 0xc000370a20, 0x0, 0x0)
        /usr/local/go/src/html/template/template.go:119 +0x2f
git.imaxinacion.net/uoe/anssid/app/resource.(*Resource).ExecTemplate(0xc0002ee120, 0x4a901b0, 0xc000374680, 0x16577a3, 0x5, 0x1660b7a, 0x10, 0x15ed6c0, 0xc000370a20, 0x145de5e, ...)
        /Users/gbemirojiboye/go/src/git.imaxinacion.net/uoe/anssid/app/resource/resource.go:110 +0x1ef

Что может быть причиной этого?

Когда я создавал новый шаблон для каждого звонка, этого не происходило.


person gbenroscience    schedule 27.07.2019    source источник


Ответы (1)


Проблема в том, что t не определен из-за затенения переменных:

t, ok := res.FetchTemplate(name)
if !ok{
    t := template.New(name) // <---- The problem is here
    t, err := t.ParseFiles(res.Assets + path)

В вашем блоке if вы переопределяете t с помощью t := .... Это означает, что у вас есть новый t с локальной областью видимости, и как только вы покинете блок if, у вас все еще будет внешний t, который по-прежнему равен `nils.

Измените отмеченную строку на:

    t = template.New(name)
person Flimzy    schedule 27.07.2019
comment
Вот это да. Не могу поверить, что пропустил это. Он был хорошо спрятан на виду. Огромное спасибо. Буду тестировать и возвращать - person gbenroscience; 27.07.2019
comment
Я тоже поначалу пропустил, видимо. Легко ошибиться :) - person Flimzy; 27.07.2019