Repository: go
Issue: proposal: html/template: building pages dynamically with one function call
Labels: Proposal

# Enhancing `html/template` for Dynamic Template Composition

## Proposal Details:

The Go programming language has become a favored choice for building robust web services, thanks in part to its efficiency and simplicity. However, when it comes to rendering web pages with the `html/template` package, developers often face the challenge of managing multiple template files. The current process requires parsing each template file individually before execution, leading to redundant code and decreased maintainability, especially in projects with extensive use of templates.

## Objective:

To address this, I propose the introduction of a new feature within the `html/template` package to enable dynamic and automated parsing of sub-templates directly from a base template. This feature aims to reduce boilerplate code, enhance code cleanliness, and streamline the development process.

## Feature Description:

**Automated Sub-Template Parsing**: Allow a base template to automatically include and parse all associated sub-templates without explicitly listing each file. This mechanism would dynamically identify and load sub-templates referenced within the base template, simplifying the template rendering process.

**New Functionality, No Breaking Changes**: This feature would be introduced as an additional function within the `html/template` package, ensuring backward compatibility and no disruption to existing codebases. It would offer developers the choice between the traditional method and this new, more streamlined approach.

**Benefits for RESTful Web Services**: As Go continues to gain popularity for developing RESTful web services that adhere to the principles of Roy Fielding and HATEOS, standardizing template management could significantly benefit developers. A common, efficient method for handling template parsing would encourage cleaner code, reduce the likelihood of custom, error-prone solutions, and promote best practices within the Go community.

## Proposed API Changes
### Introduction of a New Function for Dynamic Template Loading
**Function Name**: `ParseBaseTemplate`
**Signature**: `func ParseBaseTemplate(filePath string) (*Template, error)`
This function initializes and returns a new template based on the base template file specified by `filePath`. It scans the base template for references to sub-templates and automatically loads these sub-templates into the template object. The function is designed to streamline the process of working with complex templates by eliminating the need to manually parse each file.

### Enhancement to Template Delimiters for Sub-Template Inclusion
The function will parse the base template to identify references to sub-templates. This could leverage existing template actions (e.g., {{template "name"}}) or a predefined pattern to denote template inclusion, ensuring the function can accurately discover and load all necessary sub-templates.

### Dynamic Sub-Template Loading:
Upon identifying a sub-template reference, the function will resolve the file path (relative to the base template or a predefined template directory) and parse the sub-template. This process repeats recursively for any sub-templates referenced within other sub-templates, ensuring a comprehensive template hierarchy is constructed.

### Error Handling and Reporting Enhancements
With the introduction of dynamic sub-template loading, enhanced error handling and reporting mechanisms are necessary to ensure developers can easily debug issues related to template parsing. This includes clear error messages for missing sub-templates, circular references, or parsing errors within dynamically included templates.

### Example Usage
Here's a hypothetical example demonstrating how a developer might use the new `ParseBaseTemplate` function:

```go
package main

import (
    "html/template"
    "net/http"
)

func main() {
    // Dynamically load the base template along with all referenced sub-templates
    tmpl, err := template.ParseBaseTemplate("views/base.html")
    if err != nil {
        panic(err) // Handle error appropriately
    }

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // Execute the base template, with all necessary sub-templates included
        err := tmpl.Execute(w, nil)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    })

    http.ListenAndServe(":8080", nil)
}
```
In this example, the developer only needs to call `ParseBaseTemplate` once to load the base template along with all its sub-templates, based on the references within the base template. This significantly reduces boilerplate code and simplifies the template management process.

### Before & After
#### Before:
```go
tmpl, err := template.ParseFiles(
  "template/base.html",
  "template/common/footer.html",
  "template/common/nav/index.html",
  "template/common/nav/search.html",
  "template/page/index.html",
  "template/page/content/thing/index.html",
  ...list of files grows without an end in sight
)
```
#### After:
```go
 tmpl, err := template.ParseBaseTemplate("template/base.html")
```

## Rationale:

The motivation behind this proposal is to address a growing need within the Go ecosystem for more efficient template management. As web applications become more complex and the use of templates increases, the ability to dynamically manage these templates becomes crucial. By providing a standard solution within the standard library, we can enhance developer productivity, ensure code quality, and foster innovation in Go-based web services.

## Conclusion:

Introducing dynamic template composition into the `html/template` package represents a significant step forward in improving the developer experience and code quality for Go-based web applications. By reducing redundancy and streamlining the template handling process, we can unlock new possibilities for web development in Go, aligning with the language's philosophy of simplicity and efficiency.