2016-12-16 18 views
9

w pakietach html/template (i text/template) template.New ma następujący podpis:Go nazwa szablonu

func New(name string) *Template 

Czym dokładnie jest name używany? Zeskanowałem dokumenty (i trochę źródła), ale bezskutecznie. Po prostu stwórz wszystkie moje szablony z pustym łańcuchem i nie ma to znaczenia. Dlaczego powinienem zawracać sobie głowę nazwą?

Nawet nazywania szablonów, dwa wydają równowartość:

template.Must(template.New("").Parse(`{{ define "body" }}Body{{ end }}`)) 
template.Must(template.New("body").Parse(`Body`)) 

https://play.golang.org/p/wKzCHdLf2S

Odpowiedz

10

Nazwa szablonu - niespodziewanie - to nazwa szablon.

Co jest dobre dla? Tak długo, jak nie chcesz, aby odnosiło się do szablonu, nie ma to znaczenia. Ale jeśli chcesz skierować do niego, to tak, odnosisz się do niego poprzez jego nazwę o nazwie.

Kiedy chciałbyś się z nim zapoznać? Jeśli chcesz dołączyć szablon do innego, np. za pomocą akcji {{template}} lub gdy chcesz uruchomić określony szablon za pomocą Template.ExecuteTemplate().

Jak dotąd tak dobrze, ale wciąż brakuje kluczowego punktu. Nie jest to jednoznaczne/banalne: wartość to "reprezentacja przeanalizowanego szablonu". Ale sformułowanie tutaj jest trochę "niedoskonałe". Wartość template.Template może być (i zwykle jest) zbiorem wielu powiązanych szablonów. template.Template ma pole unexported:

tmpl map[string]*Template // Map from name to defined templates. 

To pole tmpl posiada wszystkie inne związane szablony, szablony, które są widoczne na szablonie, a które mogą być określane przez ich -yes- nazw.

Podczas analizowania wielu szablony na raz, używając Template.ParseFiles() lub Template.ParseGlob(), następnie szablony zostanie nazwany przez nazwę pliku i będą wiązać się automatycznie (wyżej wymienione funkcje zwracają pojedynczą wartość template.Template, który posiada wszystko przeanalizowane szablony, powiązane).Doc of Template.ParseFiles() jest jasny na ten temat:

ParseFiles tworzy nowy szablon i analizuje definicje szablonów z nazwanych plików. Zwrócona nazwa szablonu będzie zawierała nazwę podstawową i parsowaną zawartość pierwszego pliku. [...]

Podczas analizowania wielu plików o tej samej nazwie w różnych katalogach, ostatnia wymieniona będzie tą, która się pojawi. Na przykład, ParseFiles ("a/foo", "b/foo") przechowuje "b/foo" jako szablon o nazwie "foo", a "a/foo" jest niedostępny.

Nazwa szablonu może pochodzić z wielu miejsca:

  • może pochodzić od nazwy pliku (jak widać powyżej)
  • może być jednoznacznie określony (jeśli jest zdefiniowana za pomocą {{define "somename"}} lub {{block "somename"}} działań)
  • lub może być określone jako argument przekazywany do template.New() (funkcja) lub Template.New() (metoda).

Zobaczmy kilka przykładów:

func main() { 
    t := template.Must(template.New("one").Parse(t1src)) 
    template.Must(t.New("other").Parse(t2src)) 

    // error checks omitted for brevity 
    // Executes default, "one": 
    t.Execute(os.Stdout, nil) 

    // Executes explicit, "one": 
    t.ExecuteTemplate(os.Stdout, "one", nil) 

    // Executes explicit, "other": 
    t.ExecuteTemplate(os.Stdout, "other", nil) 
} 

const t1src = `I'm some template. 
` 
const t2src = `I'm some OTHER template. 
` 

Output (spróbuj na Go Playground):

I'm some template. 
I'm some template. 
I'm some OTHER template. 

Jeśli teraz iść do przodu, a następnie zmień pierwsze 2 linie do tego:

t := template.Must(template.New("one").Parse(t1src)) 
t = template.Must(t.New("other").Parse(t2src)) 

To, co się tutaj dzieje, to to, że my assi uzyskała nową wartość template.Template na t, która była wynikiem analizowania t2src, więc będzie to wartość domyślna, ale nadal oba szablony mogą zostać "osiągnięte" z niej, ponieważ są z nią powiązane. Zmiany do tego wyjścia (spróbuj go na Go Playground):

I'm some OTHER template. 
I'm some template. 
I'm some OTHER template. 

Wywołanie template.New() (Funkcja) tworzy nowy szablon, związane żadne. Podczas wywoływania metody Template.New() (metoda) zwrócony szablon zostanie powiązany z (wszystkimi) szablonami, do których wywołana jest metoda.

Zobaczmy teraz kilka przykładów dotyczących "osadzonych" szablonów.

func main() { 
    t := template.Must(template.New("one").Parse(t1src)) 
    template.Must(t.New("other").Parse(t2src)) 
    template.Must(t.New("third").Parse(t3src)) 

    t.Execute(os.Stdout, nil) 
    t.ExecuteTemplate(os.Stdout, "one", nil) 
    t.ExecuteTemplate(os.Stdout, "other", nil) 
    t.ExecuteTemplate(os.Stdout, "embedded", nil) 
    t.ExecuteTemplate(os.Stdout, "third", nil) 
} 

const t1src = `I'm some template. {{block "embedded" .}}I'm embedded in "one". 
{{end}}` 
const t2src = `I'm some OTHER template. 
` 
const t3src = `I'm the 3rd, including everything from "one": {{template "one"}} 
` 

Output (spróbuj go na Go Playground):

I'm some template. I'm embedded in "one". 
I'm some template. I'm embedded in "one". 
I'm some OTHER template. 
I'm embedded in "one". 
I'm the 3rd, including everything from "one": I'm some template. I'm embedded in "one". 

Powinno być oczywiste, teraz, jaka jest rola nazwy szablonu jest i skąd pochodzi.

4

Jest on używany do renderowania powiązanych szablonów.

Na przykład:

tmpl := template.Must(template.New("body").Parse(` 
    {{ define "body" }} 
     Body 
    {{ end }} 
    `)) 

tmpl = template.Must(tmpl.New("base").Parse(` 
    Start of base template 

    {{ template "body" }} 

    End of base template 
    `)) 

tmpl = template.Must(tmpl.New("baz").Parse(` 
    Start of baz template 

    {{ template "body" }} 

    End of baz template 
    `)) 

tmpl.ExecuteTemplate(os.Stdout, "base", nil) 
tmpl.ExecuteTemplate(os.Stdout, "baz", nil) 

Play Example

wyjściowa:

 Start of base template 


     Body 


    End of base template 

    Start of baz template 


     Body 


    End of baz template 

tmpl.ExecuteTemplate(os.Stdout, "base", nil) odda szablonu za pomocą "baza" szablon

tmpl.ExecuteTemplate(os.Stdout, "baz", nil) odda szablonu za pomocą "b "szablon"

+0

Poza tym, że jeśli zmienię ten pierwszy wiersz na "template.New (" ")', to działa równie dobrze. https://play.golang.org/p/zQoGalIxFq Ale myślę, że coś knujesz. Wydaje się, że 'ExecuteTemplate' nie działa bez nazywania szablonu" podstawowego ". – Dave

+0

Oto ten sam przykład, ale z pustymi ciągami dla wszystkich nazw szablonów. https://play.golang.org/p/0NdJ1j_ype Wygląda na to, że '{{define" name "}}' działa jako alternatywa dla nazwania szablonu w metodzie 'New'. – Dave

+0

@Dave i dodałem trzeci szablon, aby lepiej zilustrować użyteczność nazwanego szablonu. – jmaloney