Popularity
5.3
Growing
Activity
3.8
Declining
180
5
18

Programming language: Go
Tags: Template Engines    
Latest version: v0.3.0

goview alternatives and similar packages

Based on the "Template Engines" category

Do you think we are missing an alternative of goview or a related project?

Add another 'Template Engines' Package

README

goview

GoDoc Widget Travis Widget GoReportCard Widget

Goview is a lightweight, minimalist and idiomatic template library based on golang html/template for building Go web application.

Contents

Install

go get github.com/foolin/goview

Features

  • Lightweight - use golang html/template syntax.
  • Easy - easy use for your web application.
  • Fast - Support configure cache template.
  • Include syntax - Support include file.
  • Master layout - Support configure master layout file.
  • Extension - Support configure template file extension.
  • Easy - Support configure templates directory.
  • Auto reload - Support dynamic reload template(disable cache mode).
  • Multiple Engine - Support multiple templates for frontend and backend.
  • No external dependencies - plain ol' Go html/template.
  • Gorice - Support gorice for package resources.
  • Gin/Iris/Echo/Chi - Support gin framework, Iris framework, echo framework, go-chi framework.

Docs

See https://www.godoc.org/github.com/foolin/goview

Supports

Usage

Overview

Project structure:

|-- app/views/
    |--- index.html          
    |--- page.html
    |-- layouts/
        |--- footer.html
        |--- master.html

Use default instance:

    //write http.ResponseWriter
    //"index" -> index.html
    goview.Render(writer, http.StatusOK, "index", goview.M{})

Use new instance with config:


    gv := goview.New(goview.Config{
        Root:      "views",
        Extension: ".tpl",
        Master:    "layouts/master",
        Partials:  []string{"partials/ad"},
        Funcs: template.FuncMap{
            "sub": func(a, b int) int {
                return a - b
            },
            "copy": func() string {
                return time.Now().Format("2006")
            },
        },
        DisableCache: true,
    })

    //Set new instance
    goview.Use(gv)

    //write http.ResponseWriter
    goview.Render(writer, http.StatusOK, "index", goview.M{})

Use multiple instance with config:

    //============== Frontend ============== //
    gvFrontend := goview.New(goview.Config{
        Root:      "views/frontend",
        Extension: ".tpl",
        Master:    "layouts/master",
        Partials:  []string{"partials/ad"},
        Funcs: template.FuncMap{
            "sub": func(a, b int) int {
                return a - b
            },
            "copy": func() string {
                return time.Now().Format("2006")
            },
        },
        DisableCache: true,
    })

    //write http.ResponseWriter
    gvFrontend.Render(writer, http.StatusOK, "index", goview.M{})

    //============== Backend ============== //
    gvBackend := goview.New(goview.Config{
        Root:      "views/backend",
        Extension: ".tpl",
        Master:    "layouts/master",
        Partials:  []string{"partials/ad"},
        Funcs: template.FuncMap{
            "sub": func(a, b int) int {
                return a - b
            },
            "copy": func() string {
                return time.Now().Format("2006")
            },
        },
        DisableCache: true,
    })

    //write http.ResponseWriter
    gvBackend.Render(writer, http.StatusOK, "index", goview.M{})

Config

goview.Config{
    Root:      "views", //template root path
    Extension: ".tpl", //file extension
    Master:    "layouts/master", //master layout file
    Partials:  []string{"partials/head"}, //partial files
    Funcs: template.FuncMap{
        "sub": func(a, b int) int {
            return a - b
        },
        // more funcs
    },
    DisableCache: false, //if disable cache, auto reload template file for debug.
}

Include syntax

//template file
{{include "layouts/footer"}}

Render name:

Render name use index without .html extension, that will render with master layout.

  • "index" - Render with master layout.
  • "index.html" - Not render with master layout.
Notice: `.html` is default template extension, you can change with config

Render with master

//use name without extension `.html`
goview.Render(w, http.StatusOK, "index", goview.M{})

The w is instance of http.ResponseWriter

Render only file(not use master layout)

//use full name with extension `.html`
goview.Render(w, http.StatusOK, "page.html", goview.M{})

Custom template functions

We have two type of functions global functions, and temporary functions.

Global functions are set within the config.

goview.Config{
    Funcs: template.FuncMap{
        "reverse": e.Reverse,
    },
}
//template file
{{ reverse "route-name" }}

Temporary functions are set inside the handler.

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    err := goview.Render(w, http.StatusOK, "index", goview.M{
        "reverse": e.Reverse,
    })
    if err != nil {
        fmt.Fprintf(w, "Render index error: %v!", err)
    }
})
//template file
{{ call $.reverse "route-name" }}

Examples

See _examples/ for a variety of examples.

Basic example


package main

import (
    "fmt"
    "github.com/foolin/goview"
    "net/http"
)

func main() {

    //render index use `index` without `.html` extension, that will render with master layout.
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        err := goview.Render(w, http.StatusOK, "index", goview.M{
            "title": "Index title!",
            "add": func(a int, b int) int {
                return a + b
            },
        })
        if err != nil {
            fmt.Fprintf(w, "Render index error: %v!", err)
        }

    })

    //render page use `page.tpl` with '.html' will only file template without master layout.
    http.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
        err := goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})
        if err != nil {
            fmt.Fprintf(w, "Render page.html error: %v!", err)
        }
    })

    fmt.Println("Listening and serving HTTP on :9090")
    http.ListenAndServe(":9090", nil)

}

Project structure:

|-- app/views/
    |--- index.html          
    |--- page.html
    |-- layouts/
        |--- footer.html
        |--- master.html


See in "examples/basic" folder

Basic example

Gin example

go get github.com/foolin/goview/supports/ginview

package main

import (
    "github.com/foolin/goview/supports/ginview"
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    router := gin.Default()

    //new template engine
    router.HTMLRender = ginview.Default()

    router.GET("/", func(ctx *gin.Context) {
        //render with master
        ctx.HTML(http.StatusOK, "index", gin.H{
            "title": "Index title!",
            "add": func(a int, b int) int {
                return a + b
            },
        })
    })

    router.GET("/page", func(ctx *gin.Context) {
        //render only file, must full name with extension
        ctx.HTML(http.StatusOK, "page.html", gin.H{"title": "Page file title!!"})
    })

    router.Run(":9090")
}

Project structure:

|-- app/views/
    |--- index.html          
    |--- page.html
    |-- layouts/
        |--- footer.html
        |--- master.html


See in "examples/basic" folder

Gin example

Iris example

$ go get github.com/foolin/goview/supports/irisview
package main

import (
    "github.com/foolin/goview/supports/irisview"
    "github.com/kataras/iris/v12"
)

func main() {
    app := iris.New()

    // Register the goview template engine.
    app.RegisterView(irisview.Default())

    app.Get("/", func(ctx iris.Context) {
        // Render with master.
        ctx.View("index", iris.Map{
            "title": "Index title!",
            "add": func(a int, b int) int {
                return a + b
            },
        })
    })

    app.Get("/page", func(ctx iris.Context) {
        // Render only file, must full name with extension.
        ctx.View("page.html", iris.Map{"title": "Page file title!!"})
    })

    app.Listen(":9090")
}

Project structure:

|-- app/views/
    |--- index.html          
    |--- page.html
    |-- layouts/
        |--- footer.html
        |--- master.html


See in "examples/iris" folder

Iris example

Iris multiple example

package main

import (
    "html/template"
    "time"

    "github.com/foolin/goview"
    "github.com/foolin/goview/supports/irisview"
    "github.com/kataras/iris/v12"
)

func main() {
    app := iris.New()

    // Register a new template engine.
    app.RegisterView(irisview.New(goview.Config{
        Root:      "views/frontend",
        Extension: ".html",
        Master:    "layouts/master",
        Partials:  []string{"partials/ad"},
        Funcs: template.FuncMap{
            "copy": func() string {
                return time.Now().Format("2006")
            },
        },
        DisableCache: true,
    }))

    app.Get("/", func(ctx iris.Context) {
        ctx.View("index", iris.Map{
            "title": "Frontend title!",
        })
    })

    //=========== Backend ===========//

    // Assign a new template middleware.
    mw := irisview.NewMiddleware(goview.Config{
        Root:      "views/backend",
        Extension: ".html",
        Master:    "layouts/master",
        Partials:  []string{},
        Funcs: template.FuncMap{
            "copy": func() string {
                return time.Now().Format("2006")
            },
        },
        DisableCache: true,
    })

    backendGroup := app.Party("/admin", mw)

    backendGroup.Get("/", func(ctx iris.Context) {
        // Use the ctx.View as you used to. Zero changes to your codebase,
        // even if you use multiple templates.
        ctx.View("index", iris.Map{
            "title": "Backend title!",
        })
    })

    app.Listen(":9090")
}

Project structure:

|-- app/views/
    |-- fontend/
        |--- index.html
        |-- layouts/
            |--- footer.html
            |--- head.html
            |--- master.html
        |-- partials/
           |--- ad.html
    |-- backend/
        |--- index.html
        |-- layouts/
            |--- footer.html
            |--- head.html
            |--- master.html

See in "examples/iris-multiple" folder

Iris multiple example

Echo example

Echo <=v3 version:

go get github.com/foolin/goview/supports/echoview

Echo v4 version:

go get github.com/foolin/goview/supports/echoview-v4

package main

import (
    "github.com/foolin/goview/supports/echoview"
    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
    "net/http"
)

func main() {

    // Echo instance
    e := echo.New()

    // Middleware
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    //Set Renderer
    e.Renderer = echoview.Default()

    // Routes
    e.GET("/", func(c echo.Context) error {
        //render with master
        return c.Render(http.StatusOK, "index", echo.Map{
            "title": "Index title!",
            "add": func(a int, b int) int {
                return a + b
            },
        })
    })

    e.GET("/page", func(c echo.Context) error {
        //render only file, must full name with extension
        return c.Render(http.StatusOK, "page.html", echo.Map{"title": "Page file title!!"})
    })

    // Start server
    e.Logger.Fatal(e.Start(":9090"))
}

Project structure:

|-- app/views/
    |--- index.html          
    |--- page.html
    |-- layouts/
        |--- footer.html
        |--- master.html


See in "examples/basic" folder

Echo example Echo v4 example

Go-chi example


package main

import (
    "fmt"
    "github.com/foolin/goview"
    "github.com/go-chi/chi"
    "net/http"
)

func main() {

    r := chi.NewRouter()

    //render index use `index` without `.html` extension, that will render with master layout.
    r.Get("/", func(w http.ResponseWriter, r *http.Request) {
        err := goview.Render(w, http.StatusOK, "index", goview.M{
            "title": "Index title!",
            "add": func(a int, b int) int {
                return a + b
            },
        })
        if err != nil {
            fmt.Fprintf(w, "Render index error: %v!", err)
        }
    })

    //render page use `page.tpl` with '.html' will only file template without master layout.
    r.Get("/page", func(w http.ResponseWriter, r *http.Request) {
        err := goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})
        if err != nil {
            fmt.Fprintf(w, "Render page.html error: %v!", err)
        }
    })

    fmt.Println("Listening and serving HTTP on :9090")
    http.ListenAndServe(":9090", r)

}

Project structure:

|-- app/views/
    |--- index.html          
    |--- page.html
    |-- layouts/
        |--- footer.html
        |--- master.html


See in "examples/basic" folder

Chi example

Advance example


package main

import (
    "fmt"
    "github.com/foolin/goview"
    "html/template"
    "net/http"
    "time"
)

func main() {

    gv := goview.New(goview.Config{
        Root:      "views",
        Extension: ".tpl",
        Master:    "layouts/master",
        Partials:  []string{"partials/ad"},
        Funcs: template.FuncMap{
            "sub": func(a, b int) int {
                return a - b
            },
            "copy": func() string {
                return time.Now().Format("2006")
            },
        },
        DisableCache: true,
    })

    //Set new instance
    goview.Use(gv)

    //render index use `index` without `.html` extension, that will render with master layout.
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        err := goview.Render(w, http.StatusOK, "index", goview.M{
            "title": "Index title!",
            "add": func(a int, b int) int {
                return a + b
            },
        })
        if err != nil {
            fmt.Fprintf(w, "Render index error: %v!", err)
        }

    })

    //render page use `page.tpl` with '.html' will only file template without master layout.
    http.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
        err := goview.Render(w, http.StatusOK, "page.tpl", goview.M{"title": "Page file title!!"})
        if err != nil {
            fmt.Fprintf(w, "Render page.html error: %v!", err)
        }
    })

    fmt.Println("Listening and serving HTTP on :9090")
    http.ListenAndServe(":9090", nil)
}

Project structure:

|-- app/views/
    |--- index.tpl          
    |--- page.tpl
    |-- layouts/
        |--- footer.tpl
        |--- head.tpl
        |--- master.tpl
    |-- partials/
        |--- ad.tpl


See in "examples/advance" folder

Advance example

Multiple example


package main

import (
    "html/template"
    "net/http"
    "time"

    "github.com/foolin/goview"
    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.Default()

    //new template engine
    router.HTMLRender = gintemplate.New(gintemplate.TemplateConfig{
        Root:      "views/fontend",
        Extension: ".html",
        Master:    "layouts/master",
        Partials:  []string{"partials/ad"},
        Funcs: template.FuncMap{
            "copy": func() string {
                return time.Now().Format("2006")
            },
        },
        DisableCache: true,
    })

    router.GET("/", func(ctx *gin.Context) {
        // `HTML()` is a helper func to deal with multiple TemplateEngine's.
        // It detects the suitable TemplateEngine for each path automatically.
        gintemplate.HTML(ctx, http.StatusOK, "index", gin.H{
            "title": "Fontend title!",
        })
    })

    //=========== Backend ===========//

    //new middleware
    mw := gintemplate.NewMiddleware(gintemplate.TemplateConfig{
        Root:      "views/backend",
        Extension: ".html",
        Master:    "layouts/master",
        Partials:  []string{},
        Funcs: template.FuncMap{
            "copy": func() string {
                return time.Now().Format("2006")
            },
        },
        DisableCache: true,
    })

    // You should use helper func `Middleware()` to set the supplied
    // TemplateEngine and make `HTML()` work validly.
    backendGroup := router.Group("/admin", mw)

    backendGroup.GET("/", func(ctx *gin.Context) {
        // With the middleware, `HTML()` can detect the valid TemplateEngine.
        gintemplate.HTML(ctx, http.StatusOK, "index", gin.H{
            "title": "Backend title!",
        })
    })

    router.Run(":9090")
}


Project structure:

|-- app/views/
    |-- fontend/
        |--- index.html
        |-- layouts/
            |--- footer.html
            |--- head.html
            |--- master.html
        |-- partials/
           |--- ad.html
    |-- backend/
        |--- index.html
        |-- layouts/
            |--- footer.html
            |--- head.html
            |--- master.html

See in "examples/multiple" folder

Multiple example

go.rice example

go get github.com/foolin/goview/supports/gorice

package main

import (
    "fmt"
    "github.com/GeertJohan/go.rice"
    "github.com/foolin/goview"
    "github.com/foolin/goview/supports/gorice"
    "net/http"
)

func main() {

    //static
    staticBox := rice.MustFindBox("static")
    staticFileServer := http.StripPrefix("/static/", http.FileServer(staticBox.HTTPBox()))
    http.Handle("/static/", staticFileServer)

    //new view engine
    gv := gorice.New(rice.MustFindBox("views"))
    //set engine for default instance
    goview.Use(gv)

    //render index use `index` without `.html` extension, that will render with master layout.
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        err := goview.Render(w, http.StatusOK, "index", goview.M{
            "title": "Index title!",
            "add": func(a int, b int) int {
                return a + b
            },
        })
        if err != nil {
            fmt.Fprintf(w, "Render index error: %v!", err)
        }

    })

    //render page use `page.tpl` with '.html' will only file template without master layout.
    http.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
        err := goview.Render(w, http.StatusOK, "page.html", goview.M{"title": "Page file title!!"})
        if err != nil {
            fmt.Fprintf(w, "Render page.html error: %v!", err)
        }
    })

    fmt.Println("Listening and serving HTTP on :9090")
    http.ListenAndServe(":9090", nil)
}

Project structure:

|-- app/views/
    |--- index.html          
    |--- page.html
    |-- layouts/
        |--- footer.html
        |--- master.html
|-- app/static/  
    |-- css/
        |--- bootstrap.css      
    |-- img/
        |--- gopher.png

See in "examples/gorice" folder

gorice example

More examples

See _examples/ for a variety of examples.

Todo

[ ] Add Partials support directory or glob [ ] Add functions support.