2016-11-14 2 views
1

그래서 어떻게 든 내 {{ .blahblah }} 동작을 템플릿에서 문자열 조각으로 정의하려고합니다. 내가 []string{"name", "age"}를 얻을 수 있도록하고 싶습니다Golang, 구문 분석 된 템플릿에서 '동작'템플릿 또는지도 목록을 가져 오는 방법은 무엇입니까?

<h1>{{ .name }} {{ .age }}</h1> 

: 예를 들어

나는이 템플릿이있는 경우.

t := template.New("cooltemplate").Parse(`<h1>{{ .name }} {{ .age }}</h1>`) 
if t.Fields() == []string{"name", "age"} { 
    fmt.Println("Yay, now I know what fields I can pass in!") 
    // Now lets pass in the name field that we just discovered. 
    _ = t.Execute(os.Stdout, map[string]string{"name": "Jack", "age":"120"}) 
} 

이 같은 분석 템플릿을 검사 할 수있는 방법이 있나요 : 템플릿 메소드 func (t *Template) Fields() []string을 가지고 척?
감사합니다.

+0

템플릿은 이런 종류의 물건 (FieldNode)를 노출하는 parse.Tree이 포함되어 있습니다. 문서 양식 : "* parse.Tree 필드는 html/template에서만 사용할 수 있도록 내보내고 다른 모든 클라이언트에서는 unexported로 처리해야합니다." So : 그렇게하지 마십시오. 당신이 그 충고를 따르지 않는다면 : 행운을 빌어 요. – Volker

답변

0

머리말 : Voker에서 설명한 것처럼 Template.Tree 필드는 "html/template에서만 사용하도록 내 보낸 이며 다른 모든 클라이언트는이를 안심하고 처리해야합니다."

템플릿 실행에 입력을 제공하는 데 의존해서는 안됩니다. 필요한 데이터와 함께 실행하려는 템플릿을 알아야합니다. 런타임에 인수를 제공하기 위해 "탐색"해서는 안됩니다.


템플릿을 구문 분석 나가 값은 template.Template입니다 (하나 text/template 또는 html/template, 그들은 같은 API를). 이 템플리트는 템플리트를 parse.Tree 유형의 트리로 표시합니다. 텍스트 템플릿에 포함 된 모든 것은 정적 텍스트, 동작 등을 포함하여 노드의이 트리에 저장됩니다.

그렇다고해서이 트리를 걸 으면 필드 나 호출 기능에 액세스하는 작업을 식별하는 노드를 찾을 수 있습니다. 노드 유형이 Node.Type()parse.Node 유형입니다. 가능한 유형은 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}}] 
+0

답변 해 주셔서 감사합니다. 명확하게하기 위해 런타임에 작업을 얻으려는 이유는 템플릿 작성을 제어하지 못하거나 템플릿이 자주 변경되는 경우입니다. 예를 들어 편지를 나타내는 템플릿이 있습니다. 사용자가 템플릿의 값을 입력 할 수있는 GUI가 있습니다. 분명히 모든 템플릿에는 채워질 필요가있는 유사하고 약간 다른 동작이있을 것입니다.따라서 GUI는 런타임에 템플리트에서 발견되는 모든 조치에 대한 입력 상자를 표시 할 수 있어야합니다. 그렇지 않으면 모든 단일 템플리트의 모든 입력 상자에 정적으로 코드를 작성해야합니다. – JackMordaunt