...
Run Format

Source file src/text/template/examplefiles_test.go

Documentation: text/template

  // Copyright 2012 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package template_test
  
  import (
  	"io"
  	"io/ioutil"
  	"log"
  	"os"
  	"path/filepath"
  	"text/template"
  )
  
  // templateFile defines the contents of a template to be stored in a file, for testing.
  type templateFile struct {
  	name     string
  	contents string
  }
  
  func createTestDir(files []templateFile) string {
  	dir, err := ioutil.TempDir("", "template")
  	if err != nil {
  		log.Fatal(err)
  	}
  	for _, file := range files {
  		f, err := os.Create(filepath.Join(dir, file.name))
  		if err != nil {
  			log.Fatal(err)
  		}
  		defer f.Close()
  		_, err = io.WriteString(f, file.contents)
  		if err != nil {
  			log.Fatal(err)
  		}
  	}
  	return dir
  }
  
  // Here we demonstrate loading a set of templates from a directory.
  func ExampleTemplate_glob() {
  	// Here we create a temporary directory and populate it with our sample
  	// template definition files; usually the template files would already
  	// exist in some location known to the program.
  	dir := createTestDir([]templateFile{
  		// T0.tmpl is a plain template file that just invokes T1.
  		{"T0.tmpl", `T0 invokes T1: ({{template "T1"}})`},
  		// T1.tmpl defines a template, T1 that invokes T2.
  		{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
  		// T2.tmpl defines a template T2.
  		{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
  	})
  	// Clean up after the test; another quirk of running as an example.
  	defer os.RemoveAll(dir)
  
  	// pattern is the glob pattern used to find all the template files.
  	pattern := filepath.Join(dir, "*.tmpl")
  
  	// Here starts the example proper.
  	// T0.tmpl is the first name matched, so it becomes the starting template,
  	// the value returned by ParseGlob.
  	tmpl := template.Must(template.ParseGlob(pattern))
  
  	err := tmpl.Execute(os.Stdout, nil)
  	if err != nil {
  		log.Fatalf("template execution: %s", err)
  	}
  	// Output:
  	// T0 invokes T1: (T1 invokes T2: (This is T2))
  }
  
  // This example demonstrates one way to share some templates
  // and use them in different contexts. In this variant we add multiple driver
  // templates by hand to an existing bundle of templates.
  func ExampleTemplate_helpers() {
  	// Here we create a temporary directory and populate it with our sample
  	// template definition files; usually the template files would already
  	// exist in some location known to the program.
  	dir := createTestDir([]templateFile{
  		// T1.tmpl defines a template, T1 that invokes T2.
  		{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
  		// T2.tmpl defines a template T2.
  		{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
  	})
  	// Clean up after the test; another quirk of running as an example.
  	defer os.RemoveAll(dir)
  
  	// pattern is the glob pattern used to find all the template files.
  	pattern := filepath.Join(dir, "*.tmpl")
  
  	// Here starts the example proper.
  	// Load the helpers.
  	templates := template.Must(template.ParseGlob(pattern))
  	// Add one driver template to the bunch; we do this with an explicit template definition.
  	_, err := templates.Parse("{{define `driver1`}}Driver 1 calls T1: ({{template `T1`}})\n{{end}}")
  	if err != nil {
  		log.Fatal("parsing driver1: ", err)
  	}
  	// Add another driver template.
  	_, err = templates.Parse("{{define `driver2`}}Driver 2 calls T2: ({{template `T2`}})\n{{end}}")
  	if err != nil {
  		log.Fatal("parsing driver2: ", err)
  	}
  	// We load all the templates before execution. This package does not require
  	// that behavior but html/template's escaping does, so it's a good habit.
  	err = templates.ExecuteTemplate(os.Stdout, "driver1", nil)
  	if err != nil {
  		log.Fatalf("driver1 execution: %s", err)
  	}
  	err = templates.ExecuteTemplate(os.Stdout, "driver2", nil)
  	if err != nil {
  		log.Fatalf("driver2 execution: %s", err)
  	}
  	// Output:
  	// Driver 1 calls T1: (T1 invokes T2: (This is T2))
  	// Driver 2 calls T2: (This is T2)
  }
  
  // This example demonstrates how to use one group of driver
  // templates with distinct sets of helper templates.
  func ExampleTemplate_share() {
  	// Here we create a temporary directory and populate it with our sample
  	// template definition files; usually the template files would already
  	// exist in some location known to the program.
  	dir := createTestDir([]templateFile{
  		// T0.tmpl is a plain template file that just invokes T1.
  		{"T0.tmpl", "T0 ({{.}} version) invokes T1: ({{template `T1`}})\n"},
  		// T1.tmpl defines a template, T1 that invokes T2. Note T2 is not defined
  		{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
  	})
  	// Clean up after the test; another quirk of running as an example.
  	defer os.RemoveAll(dir)
  
  	// pattern is the glob pattern used to find all the template files.
  	pattern := filepath.Join(dir, "*.tmpl")
  
  	// Here starts the example proper.
  	// Load the drivers.
  	drivers := template.Must(template.ParseGlob(pattern))
  
  	// We must define an implementation of the T2 template. First we clone
  	// the drivers, then add a definition of T2 to the template name space.
  
  	// 1. Clone the helper set to create a new name space from which to run them.
  	first, err := drivers.Clone()
  	if err != nil {
  		log.Fatal("cloning helpers: ", err)
  	}
  	// 2. Define T2, version A, and parse it.
  	_, err = first.Parse("{{define `T2`}}T2, version A{{end}}")
  	if err != nil {
  		log.Fatal("parsing T2: ", err)
  	}
  
  	// Now repeat the whole thing, using a different version of T2.
  	// 1. Clone the drivers.
  	second, err := drivers.Clone()
  	if err != nil {
  		log.Fatal("cloning drivers: ", err)
  	}
  	// 2. Define T2, version B, and parse it.
  	_, err = second.Parse("{{define `T2`}}T2, version B{{end}}")
  	if err != nil {
  		log.Fatal("parsing T2: ", err)
  	}
  
  	// Execute the templates in the reverse order to verify the
  	// first is unaffected by the second.
  	err = second.ExecuteTemplate(os.Stdout, "T0.tmpl", "second")
  	if err != nil {
  		log.Fatalf("second execution: %s", err)
  	}
  	err = first.ExecuteTemplate(os.Stdout, "T0.tmpl", "first")
  	if err != nil {
  		log.Fatalf("first: execution: %s", err)
  	}
  
  	// Output:
  	// T0 (second version) invokes T1: (T1 invokes T2: (T2, version B))
  	// T0 (first version) invokes T1: (T1 invokes T2: (T2, version A))
  }
  

View as plain text