func (r *Render) HTML(w http.ResponseWriter, status int, name string, v interface{}) error {
	w.Header().Set(ContentType, r.opts.ContentHTML)
	w.WriteHeader(status)
	if name == "" {
		return errors.New("renderer: template name not exist")
	}
	if r.opts.Debug {
		r.parseGlob()
	}
	buf := new(bytes.Buffer)
	defer buf.Reset()
	if err := r.globTemplates.ExecuteTemplate(buf, name, v); err != nil {
		return err
	}
	_, err := w.Write(buf.Bytes())
	return err
}
HTML render html from template.Glob patterns and execute template by name. See README.md for detail example.
package renderer
import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	yaml "gopkg.in/yaml.v2"
)
const (
	ContentType string = "Content-Type"
	ContentJSON string = "application/json"
	ContentJSONP string = "application/javascript"
	ContentXML string = "application/xml"
	ContentYAML string = "application/x-yaml"
	ContentHTML string = "text/html"
	ContentText string = "text/plain"
	ContentBinary string = "application/octet-stream"
	ContentDisposition string = "Content-Disposition"
	contentDispositionInline string = "inline"
	contentDispositionAttachment string = "attachment"
	defaultCharSet            string = "utf-8"
	defaultJSONPrefix         string = ""
	defaultXMLPrefix          string = `<?xml version="1.0" encoding="ISO-8859-1" ?>\n`
	defaultTemplateExt        string = "tpl"
	defaultLayoutExt          string = "lout"
	defaultTemplateLeftDelim  string = "{{"
	defaultTemplateRightDelim string = "}}"
)
type (
	M map[string]interface{}
	Options struct {
		Charset string
		ContentJSON string
		ContentJSONP string
		ContentXML string
		ContentYAML string
		ContentHTML string
		ContentText string
		ContentBinary string
		UnEscapeHTML bool
		DisableCharset bool
		Debug bool
		JSONIndent bool
		XMLIndent bool
		JSONPrefix string
		XMLPrefix string
		TemplateDir string
		TemplateExtension string
		LeftDelim string
		RightDelim string
		LayoutExtension string
		FuncMap []template.FuncMap
		ParseGlobPattern string
	}
	Render struct {
		opts          Options
		templates     map[string]*template.Template
		globTemplates *template.Template
		headers       map[string]string
	}
)
func New(opts ...Options) *Render {
	var opt Options
	if opts != nil {
		opt = opts[0]
	}
	r := &Render{
		opts:      opt,
		templates: make(map[string]*template.Template),
	}
	r.buildOptions()
	if r.opts.TemplateDir != "" {
		r.parseTemplates()
	}
	if r.opts.ParseGlobPattern != "" {
		r.parseGlob()
	}
	return r
}
func (r *Render) buildOptions() {
	if r.opts.Charset == "" {
		r.opts.Charset = defaultCharSet
	}
	if r.opts.JSONPrefix == "" {
		r.opts.JSONPrefix = defaultJSONPrefix
	}
	if r.opts.XMLPrefix == "" {
		r.opts.XMLPrefix = defaultXMLPrefix
	}
	if r.opts.TemplateExtension == "" {
		r.opts.TemplateExtension = "." + defaultTemplateExt
	} else {
		r.opts.TemplateExtension = "." + r.opts.TemplateExtension
	}
	if r.opts.LayoutExtension == "" {
		r.opts.LayoutExtension = "." + defaultLayoutExt
	} else {
		r.opts.LayoutExtension = "." + r.opts.LayoutExtension
	}
	if r.opts.LeftDelim == "" {
		r.opts.LeftDelim = defaultTemplateLeftDelim
	}
	if r.opts.RightDelim == "" {
		r.opts.RightDelim = defaultTemplateRightDelim
	}
	r.opts.ContentJSON = ContentJSON
	r.opts.ContentJSONP = ContentJSONP
	r.opts.ContentXML = ContentXML
	r.opts.ContentYAML = ContentYAML
	r.opts.ContentHTML = ContentHTML
	r.opts.ContentText = ContentText
	r.opts.ContentBinary = ContentBinary
	if !r.opts.DisableCharset {
		r.enableCharset()
	}
}
func (r *Render) enableCharset() {
	r.opts.ContentJSON = fmt.Sprintf("%s; charset=%s", r.opts.ContentJSON, r.opts.Charset)
	r.opts.ContentJSONP = fmt.Sprintf("%s; charset=%s", r.opts.ContentJSONP, r.opts.Charset)
	r.opts.ContentXML = fmt.Sprintf("%s; charset=%s", r.opts.ContentXML, r.opts.Charset)
	r.opts.ContentYAML = fmt.Sprintf("%s; charset=%s", r.opts.ContentYAML, r.opts.Charset)
	r.opts.ContentHTML = fmt.Sprintf("%s; charset=%s", r.opts.ContentHTML, r.opts.Charset)
	r.opts.ContentText = fmt.Sprintf("%s; charset=%s", r.opts.ContentText, r.opts.Charset)
	r.opts.ContentBinary = fmt.Sprintf("%s; charset=%s", r.opts.ContentBinary, r.opts.Charset)
}
func (r *Render) DisableCharset(b bool) *Render {
	r.opts.DisableCharset = b
	if !b {
		r.buildOptions()
	}
	return r
}
func (r *Render) JSONIndent(b bool) *Render {
	r.opts.JSONIndent = b
	return r
}
func (r *Render) XMLIndent(b bool) *Render {
	r.opts.XMLIndent = b
	return r
}
func (r *Render) Charset(c string) *Render {
	r.opts.Charset = c
	return r
}
func (r *Render) EscapeHTML(b bool) *Render {
	r.opts.UnEscapeHTML = b
	return r
}
func (r *Render) Delims(left, right string) *Render {
	r.opts.LeftDelim = left
	r.opts.RightDelim = right
	return r
}
func (r *Render) FuncMap(fmap template.FuncMap) *Render {
	r.opts.FuncMap = append(r.opts.FuncMap, fmap)
	return r
}
func (r *Render) NoContent(w http.ResponseWriter) error {
	w.WriteHeader(http.StatusNoContent)
	return nil
}
func (r *Render) Render(w http.ResponseWriter, status int, v interface{}) error {
	w.WriteHeader(status)
	_, err := w.Write(v.([]byte))
	return err
}
func (r *Render) String(w http.ResponseWriter, status int, v interface{}) error {
	w.Header().Set(ContentType, r.opts.ContentText)
	w.WriteHeader(status)
	_, err := w.Write([]byte(v.(string)))
	return err
}
func (r *Render) json(v interface{}) ([]byte, error) {
	var bs []byte
	var err error
	if r.opts.JSONIndent {
		bs, err = json.MarshalIndent(v, "", " ")
	} else {
		bs, err = json.Marshal(v)
	}
	if err != nil {
		return bs, err
	}
	if r.opts.UnEscapeHTML {
		bs = bytes.Replace(bs, []byte("\\u003c"), []byte("<"), -1)
		bs = bytes.Replace(bs, []byte("\\u003e"), []byte(">"), -1)
		bs = bytes.Replace(bs, []byte("\\u0026"), []byte("&"), -1)
	}
	return bs, nil
}
func (r *Render) JSON(w http.ResponseWriter, status int, v interface{}) error {
	w.Header().Set(ContentType, r.opts.ContentJSON)
	w.WriteHeader(status)
	bs, err := r.json(v)
	if err != nil {
		return err
	}
	if r.opts.JSONPrefix != "" {
		w.Write([]byte(r.opts.JSONPrefix))
	}
	_, err = w.Write(bs)
	return err
}
func (r *Render) JSONP(w http.ResponseWriter, status int, callback string, v interface{}) error {
	w.Header().Set(ContentType, r.opts.ContentJSONP)
	w.WriteHeader(status)
	bs, err := r.json(v)
	if err != nil {
		return err
	}
	if callback == "" {
		return errors.New("renderer: callback can not bet empty")
	}
	w.Write([]byte(callback + "("))
	_, err = w.Write(bs)
	w.Write([]byte(");"))
	return err
}
func (r *Render) XML(w http.ResponseWriter, status int, v interface{}) error {
	w.Header().Set(ContentType, r.opts.ContentXML)
	w.WriteHeader(status)
	var bs []byte
	var err error
	if r.opts.XMLIndent {
		bs, err = xml.MarshalIndent(v, "", " ")
	} else {
		bs, err = xml.Marshal(v)
	}
	if err != nil {
		return err
	}
	if r.opts.XMLPrefix != "" {
		w.Write([]byte(r.opts.XMLPrefix))
	}
	_, err = w.Write(bs)
	return err
}
func (r *Render) YAML(w http.ResponseWriter, status int, v interface{}) error {
	w.Header().Set(ContentType, r.opts.ContentYAML)
	w.WriteHeader(status)
	bs, err := yaml.Marshal(v)
	if err != nil {
		return err
	}
	_, err = w.Write(bs)
	return err
}
func (r *Render) HTMLString(w http.ResponseWriter, status int, html string) error {
	w.Header().Set(ContentType, r.opts.ContentHTML)
	w.WriteHeader(status)
	out := template.HTML(html)
	_, err := w.Write([]byte(out))
	return err
}