Popularity
6.1
Stable
Activity
1.2
Growing
402
6
35

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

goview alternatives and similar packages

Based on the "Template Engines" category.
Alternatively, view goview alternatives based on common mentions on social networks and blogs.

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,
    Delims:    Delims{Left: "{{", Right: "}}"},
    })

    //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,
    Delims:       Delims{Left: "{{", Right: "}}"},
    })

    //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,
    Delims:       Delims{Left: "{{", Right: "}}"},
    })

    //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.
    Delims:       Delims{Left: "{{", Right: "}}"},
}

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.