Динамические имена шаблонов [дубликат]

Из документация, связанная с :

# Features can be used to reexport features of other packages. The `session`
# feature of package `awesome` will ensure that the `session` feature of the
# package `cookie` is also enabled.
session = ["cookie/session"]
blockquote>

Достаточно ли этого?

7
задан icza 5 September 2016 в 09:13
поделиться

1 ответ

К сожалению, вы не можете.

Синтаксис действия {{template}}:

{{template "name"}}
    The template with the specified name is executed with nil data.

{{template "name" pipeline}}
    The template with the specified name is executed with dot set
    to the value of the pipeline.

Имя шаблона, которое будет включено, является константой / g3], это не конвейер , который может меняться во время исполнения на основе параметров.

Если допустимый синтаксис будет:

{{template pipeline}}

то вы можете использовать что-то вроде {{template .TemplName}}, но поскольку синтаксис допускает только постоянную строку, вы не можете.

Рассуждение от Rob, почему динамический вызов шаблона недопустим ( source ):

Мы хотим, чтобы язык шаблона был статически проанализирован, поэтому контекст вызова шаблона ясен, можно проверить и заблокировать. Если точка вызова полностью динамическая, это невозможно. Аналогично, если шаблон может принадлежать множеству множеств, его контекст может различаться между наборами таким образом, чтобы потребовалось одновременное анализ всех наборов. Поскольку оба этих ограничения легко обойти, если вы хотите, ценой потери этих статических проверок в пакете более высокого уровня, было бы разумно контролировать ситуацию в реализации базового шаблона. Пакет более высокого уровня, такой как гипотетическая обертка только для HTML, может гарантировать отсутствие обходных путей более легко, если ограничения ясны.

Альтернатива # 1: Выполнение Includable Template First

Что вы можете сделать, это выполнить шаблон, который вы хотите включить первым, и вставить результат, в который вы хотите включить его. Вы можете использовать специальные типы, чтобы не удалять результат внутреннего шаблона при вставке, например html.HTML в случае HTML-шаблонов.

См. Этот пример:

func main() {
    t := template.Must(template.New("t").Parse(t))
    template.Must(t.New("t1").Parse(t1))

    params := struct {
        Name  string
        Value interface{}
    }{"t1", nil}
    b := bytes.Buffer{}
    t.ExecuteTemplate(&b, params.Name, nil)
    params.Value = template.HTML(b.String())

    t.Execute(os.Stdout, params)
}

const t = `<html><body>
Now I will include template with name: {{.Name}}
{{.Value}}
</body>/html>`

const t1 = `I'm template <b>t1</b>.`

Выход:

<html><body>
Now I will include template with name: t1
I'm template <b>t1</b>.
</body>/html>

Попробуйте на Go Playground .

Результат шаблона t1 был вставлен без сохранения. Если вы оставите template.HTML:

params.Value = b.String()

t1 будет вставлен с экранированием, например:

<html><body>
Now I will include template with name: t1
I&#39;m template &lt;b&gt;t1&lt;/b&gt;.
</body>/html>

Альтернатива №2: Шаблоны реструктуризации

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

Пример: вы можете создать страницы, на которых у вас есть шаблон page, что-то вроде этого :

<html><body>
    Title, headers etc.
    {{template .Page}}
    Footers
</body></html>

Вы можете перестроить его таким образом:

header шаблон:

<html><body>
    Title, headers, etc.

footer шаблон:

    Footers
</body></html

И ваши шаблоны страниц будут включать header и footer следующим образом:

{{template "header" .}}
    Page content comes here.
{{template "footer" .}}

Альтернатива №3: ​​Используйте действие {{if}} и предопределенные имена

Если вы знаете имена шаблонов ранее, и это не исчерпывающий список, вы можете использовать действие шаблона {{if}} для включения нужного шаблона. Пример:

{{if eq .Name "page1"}}

    {{template "page1" .}}

{{else if eq .Name "page2"}}

    {{template "page2" .}}
    ...

{{end}}

Альтернатива №4: Изменение текста статического шаблона

Идея состоит в том, что вы можете вручную изменить статический текст внешнего шаблона и вставить имя внутренний шаблон, который вы хотите включить.

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

11
ответ дан icza 18 August 2018 в 16:58
поделиться
  • 1
    Спасибо, @icza. На самом деле, я паникую сейчас :). Я думал, что существует простой способ. Ваши варианты очень хорошие, но в моей ситуации я предпочитаю использовать, как это {{ if .IsArticle }}{{ template "article" . }}{{ else }}{{ template "page" .}}{{ end }}. Где IsArticle bool флаг, основанный на запросе пользователя (URL). – user4611478 3 March 2015 в 13:44
  • 2
    @ user4611478 Это также очень хорошая альтернатива, если вы знаете имена шаблонов ранее, и это не исчерпывающий список. Я включаю его в ответ, если вы не возражаете. – icza 3 March 2015 в 13:47
  • 3
    Спасибо, два года спустя я спросил себя, как справиться с этой ситуацией, и действительно кажется, что использование кучки {{ if }} - это действительно способ ... – Gwyneth Llewelyn 11 July 2017 в 10:11
Другие вопросы по тегам:

Похожие вопросы: