// 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 gf/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)) }