Предисловие: Как предлагает Voker, поле Template.Tree
равно «экспортировано только для использования по html/template и должно рассматриваться как нераскрытое всеми другими клиентами».
Вы не должны полагаться на такую вещь, чтобы иметь возможность предоставлять ввод для выполнения шаблона. Вы должны знать шаблон, который хотите выполнить, и данные, которые он ожидает. Вы не должны «исследовать» его во время выполнения, чтобы предоставить аргументы для него.
Значение, которое вы получите из разбора шаблона является template.Template
(либо text/template
или html/template
, они имеют один и тот же API). Этот шаблон представляет шаблоны как дерево типа parse.Tree
. Все, что содержит текстовый шаблон, хранится в этом дереве в узлах, включая статические тексты, действия и т. Д.
Сказав это, вы можете пройти это дерево и искать узлы, которые идентифицируют такие действия, которые получают доступ к полям или вызовам. Узлы имеют тип parse.Node
, который имеет метод Node.Type()
, возвращающий его тип. Возможные типы определяются как константы в пакете parse
, рядом с типом parse.NodeType
, например.
const (
NodeText NodeType = iota // Plain text.
NodeAction // A non-control action such as a field evaluation.
NodeBool // A boolean constant.
NodeChain // A sequence of field accesses.
NodeCommand // An element of a pipeline.
NodeDot // The cursor, dot.
NodeField // A field or method name.
NodeIdentifier // An identifier; always a function name.
NodeIf // An if action.
NodeList // A list of Nodes.
NodeNil // An untyped nil constant.
NodeNumber // A numerical constant.
NodePipe // A pipeline of commands.
NodeRange // A range action.
NodeString // A string constant.
NodeTemplate // A template invocation action.
NodeVariable // A $ variable.
NodeWith // A with action.
)
Так вот пример программы, которая рекурсивно проходит шаблон дерева, и выглядит для узлов с NodeAction
типа, который «акция без контроля, такие как полевой оценки.»
Это решение является просто демонстрацией, доказательством концепции, она не обрабатывает все случаи.
func ListTemplFields(t *template.Template) []string {
return listNodeFields(t.Tree.Root, nil)
}
func listNodeFields(node parse.Node, res []string) []string {
if node.Type() == parse.NodeAction {
res = append(res, node.String())
}
if ln, ok := node.(*parse.ListNode); ok {
for _, n := range ln.Nodes {
res = listNodeFields(n, res)
}
}
return res
}
Пример использования его:
t := template.Must(template.New("cooltemplate").
Parse(`<h1>{{ .name }} {{ .age }}</h1>`))
fmt.Println(ListTemplFields(t))
Выход (попробовать на Go Playground):
[{{.name}} {{.age}}]
Шаблон содержит parse.Tree который предоставляет этот вид материала (FieldNode). Формируйте документы: «Поле * parse.Tree экспортируется только для использования с помощью html/template и должно рассматриваться как не экспортированное всеми другими клиентами». Итак: Не делайте этого. Если вы не следуете этому совету: Удачи. – Volker