Экранирование "/" в шаблоне

Я хочу передать строку, подобную этой «avatars/avatar.png», но когда я передаю ее в шаблон, я получаю экранированный символ. Итак, я написал функцию, которую я передаю в шаблон:

var tpl *template.Template

func init() {
    tpl = template.Must(template.ParseGlob("1Forum/static/html/*.html"))
    tpl = tpl.Funcs(template.FuncMap{
        "unescape": func(s string) string {
            unescaped, err := url.PathUnescape(s)
            if err != nil {
                return s
            }
            return unescaped
        },
    })
}

{{unescape .User.Avatar}}

Но я продолжаю получать «функция« unescape »не определена». Разве unescape не определен?

"net/url" импортируется.

🤔 А знаете ли вы, что...
Go обладает небольшой и компактной синтаксической базой.


1
59
2

Ответы:

Сообщение об ошибке «функция« unescape »не определена» указывает на то, что определенная вами пользовательская функция недоступна в контексте шаблона. Чтобы сделать функцию доступной для вашего шаблона, вам нужно передать ее как значение методу Funcs при определении вашего шаблона:

tpl = 
template.Must(template.ParseGlob("1Forum/static/html/*.html"))
tpl = tpl.Funcs(template.FuncMap{
    "unescape": func(s string) string {
        unescaped, err := url.PathUnescape(s)
        if err != nil {
        return s
    }
    return unescaped
},

})

Обязательно передайте значение tpl методу Execute при рендеринге шаблона:

err := tpl.Execute(w, data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}

Это должно сделать функцию unescape доступной в ваших шаблонах, и вы сможете использовать ее, не сталкиваясь с ошибкой «функция «unescape» не определена».

Надеюсь, это поможет.


Решено

Разве unescape не определен?

Технически нет. Вы определяете его, но делаете это слишком поздно. Определена ли функция или нет, проверяется во время синтаксического анализа, а не выполнения. У вас есть ParseGlob, а затем вы делаете tpl.Func(...). Это не по порядку.

Вместо этого выполните:

func init() {
    tpl = template.Must(template.New("t").Funcs(template.FuncMap{
        "unescape": func(s string) string {
            unescaped, err := url.PathUnescape(s)
            if err != nil {
                return s
            }
            return unescaped
        },
    }).ParseGlob("1Forum/static/html/*.html"))
}

Обратите внимание, что экранирование, которое является функцией безопасности, происходит в зависимости от того, в каком контексте вы используете данные, и unescape, скорее всего, не поможет вам «обмануть» это, потому что экранирование будет выполняться на вывод unescape, а не его ввод.

Другими словами, когда вы делаете {{unescape .}}, синтаксический анализатор может, в зависимости от контекста, превратить это в {{unescape . | urlescaper}} (urlescaper — это внутренняя экранирующая функция). Чтобы избежать этого, если у вас есть известная безопасная строка, которую вы хотите использовать в шаблоне дословно, вы должны использовать типизированную строку вместо unescape.

См. пример детской площадки.

Для получения дополнительной информации о контекстах, экранировании, типизированных строках и т. д. прочитайте документацию пакета , там все ясно объяснено.