У меня такой код:

t, err := template.New("template").Funcs(funcMap).Parse("Howdy {{ myfunc . }}")

В таком виде все работает нормально. Но если я сделаю то же самое с ParseFiles, поместив текст выше в template.html, ничего не получится:

t, err := template.New("template").Funcs(funcMap).ParseFiles("template.html")

Мне удалось заставить ParseFiles работать в следующей форме, но не могу заставить Funcs вступить в силу:

t, err := template.ParseFiles("template.html")
t.Funcs(funcMap)

Конечно, эта последняя форма является прямым вызовом функции вместо вызова метода-получателя, так что это не одно и то же.

У кого-нибудь есть идеи, что здесь происходит? Трудно найти много деталей о шаблонах в любом.

0
meesterguyperson 6 Авг 2014 в 23:58

3 ответа

Лучший ответ

Покопался и нашел этот комментарий для template.ParseFiles в источнике:

Первый шаблон становится возвращаемым значением, если он еще не определен, и мы используем его для последующих вызовов New, чтобы связать все шаблоны вместе. Кроме того, если этот файл имеет то же имя, что и t, этот файл становится содержимым t, поэтому t, err: = New (name) .Funcs (xxx) .ParseFiles (name) работает. В противном случае мы создаем новый шаблон, связанный с t.

Таким образом, формат должен быть следующим, учитывая мой пример выше:

t, err := template.New("template.html").Funcs(funcMap).ParseFiles("path/template.html")

.New("template.html") создает пустой шаблон с заданным именем, .Funcs(funcMap) связывает любые пользовательские функции, которые мы хотим применить к нашим шаблонам, а затем .ParseFiles("path/template.html") анализирует один или несколько шаблонов с учетом этих функций и связывает содержимое с шаблоном этого имени.

Обратите внимание, что базовое имя первого файла ДОЛЖНО совпадать с именем, используемым в New. Любой проанализированный контент будет связан либо с пустым ранее существовавшим шаблоном, имеющим то же базовое имя, что и первый файл в серии, либо с новым шаблоном, имеющим это базовое имя.

Итак, в моем примере выше был создан один пустой шаблон с именем «шаблон», с которым была связана карта функций. Затем был создан новый шаблон с именем «template.html». ЭТО НЕ ОДИН! И поскольку ParseFiles был вызван последним, t оказывается шаблоном "template.html" без каких-либо прикрепленных функций.

А как насчет последнего примера? Почему это не сработало? template.ParseFiles вызывает метод получателя Parse, который, в свою очередь, применяет любые ранее зарегистрированные функции:

trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)

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

Думаю, это покрывает мой первоначальный вопрос. Дизайн здесь кажется немного неуклюжим. Нет смысла в том, что я могу связать ParseFiles с одним шаблоном и в конечном итоге вернуть другой шаблон, отличный от того, который я связываю, если они не имеют одинаковых имен. Это противоречит здравому смыслу и, вероятно, должно быть рассмотрено в будущих выпусках, чтобы избежать путаницы.

1
meesterguyperson 7 Авг 2014 в 16:03

ParseFiles должен иметь несколько имен шаблонов, которые являются базовым именем файла. Но вы вызываете template.New, он создает новый шаблон с именем error. Итак, вам следует выбрать один из шаблонов.

Foo.go

package main

import (
    "text/template"
    "log"
    "os"
    "strings"
)

func main() {
    tmpl, err := template.New("error").Funcs(template.FuncMap{
        "trim": strings.TrimSpace,
    }).ParseFiles("foo.tmpl")
    if err != nil {
        log.Fatal(err)
    }
    tmpl = tmpl.Lookup("foo.tmpl")

    err = tmpl.Execute(os.Stdout, " string contains spaces both ")
    if err != nil {
        log.Fatal(err)
    }
}

Foo.tmpl

{{. | trim}}
0
mattn 7 Авг 2014 в 03:32

Попробуй это:

var templates = template.Must(template.New("").Funcs(fmap).ParseFiles("1.tmpl, "2.tmpl"))
1
Адександр Мороз 13 Мар 2019 в 00:02