How to make templates work with gin framework?
Asked Answered
S

4

5

I am newbie to golang. To learn it I have started with a simple web app using gin framework. I have followed the gin doc & configured template file but not able to make it work. I am getting an error -

panic: html/template: pattern matches no files: `templates/*`

goroutine 1 [running]:
html/template.Must
  /usr/local/Cellar/go/1.5.2/libexec/src/html/template/template.go:330
github.com/gin-gonic/gin.(*Engine).LoadHTMLGlob
  /Users/ameypatil/deployment/go/src/github.com/gin-gonic/gin/gin.go:126
main.main()
  /Users/ameypatil/deployment/go/src/github.com/ameykpatil/gospike/main.go:17

Below is my code -

package main

import (
    "net/http"

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

func main() {
    //os.Setenv("GIN_MODE", "release")
    //gin.SetMode(gin.ReleaseMode)

    // Creates a gin router with default middleware:
    // logger and recovery (crash-free) middleware
    router := gin.Default()

    router.LoadHTMLGlob("templates/*")
    //router.LoadHTMLFiles("templates/index.tmpl")

    router.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.tmpl", gin.H{
            "title": "GoSpike",
        })
    })

    // By default it serves on :8080 unless a
    // PORT environment variable was defined.
    router.Run(":4848")
}

My directory structure is

- gospike
--- templates
------index.tmpl
--- main.go

go install command does not give any error

but on actually running, it gives the above error. I searched & there were similar issues logged on gin's github repo but they are closed now. I have tried various things but I guess I am missing something obvious. What am I missing?

Subacute answered 26/6, 2016 at 19:6 Comment(0)
C
9

I'm guessing the issue is that you're using a relative filepath to access your templates.

If I compile and run your code from the gospike directory, it works fine. But if I run gospike from any other directory, I get the same error you were seeing.

So either you need to always run gospike in the parent directory of templates, or you need to use the absolute path. You could either hard code it:

router.LoadHTMLGlob("/go/src/github.com/ameykpatil/gospike/templates/*")

or you could do something like

router.LoadHTMLGlob(filepath.Join(os.Getenv("GOPATH"),
    "src/github.com/ameykpatil/gospike/templates/*"))

but that will fail if you have multiple paths set in your GOPATH. A better long-term solution might be setting a special environment variable like TMPL_DIR, and then just using that:

router.LoadHTMLGlob(filepath.Join(os.Getenv("TMPL_DIR"), "*"))
Consultative answered 26/6, 2016 at 19:39 Comment(0)
B
1

use relative path glob will working, you can try to code

router.LoadHTMLGlob("./templates/*")

notice the . dot sign which meaning current directory, gin.Engine will load template base on templates subdirectory of current directory .

Bipropellant answered 3/1, 2021 at 2:29 Comment(1)
How about dockerfiles ?Dactylo
D
1

Here is how I do it. This walks through the directory and collects the files marked with my template suffix which is .html & then I just include all of those. I haven't seen this answer anywhere so I thought Id post it.

// START UP THE ROUTER
router := gin.Default()

var files []string
filepath.Walk("./views", func(path string, info os.FileInfo, err error) error {
    if strings.HasSuffix(path, ".html") {
        files = append(files, path)
    }
    return nil
})

router.LoadHTMLFiles(files...)

// SERVE STATICS
router.Use(static.Serve("/css", static.LocalFile("./css", true)))
router.Use(static.Serve("/js", static.LocalFile("./js", true)))
router.Use(static.Serve("/images", static.LocalFile("./images", true)))

routers.LoadBaseRoutes(router)
routers.LoadBlog(router)

router.Run(":8080")
Dose answered 10/1, 2021 at 20:39 Comment(0)
W
0

There is a multitemplate HTML render to support multi tempaltes.

You can use AddFromFiles to add multi files:

r.AddFromFiles("index", "templates/base.html", "templates/index.html")
r.AddFromFiles("article", "templates/base.html", "templates/index.html", "templates/article.html")

Or load multi files under a directory:

package main

import (
    "path/filepath"

    "github.com/gin-contrib/multitemplate"
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.New()

    r.HTMLRender = loadTemplates()

    // ...
}

func loadTemplates() multitemplate.Render {
    files, err := filepath.Glob("template/*.tmpl")
    if err != nil {
        panic("failed to load html templates: " + err.Error())
    }

    r := multitemplate.New()

    // Generate our templates map from our template/ directories
    for _, file := range files {
        r.AddFromFiles(filepath.Base(file), file)
    }

    // add other html templates directly
    r.Add("test.tmpl", someTemplate)

    return r
}

You could see more APIs in this repo you want, hope this post help :)

Weekly answered 7/9, 2021 at 3:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.