router.LoadHTMLGlob("template/*/*.html")

My wish was: load html from template directory and it's subdirecty.

for example, a template file will be template/account/register.tmpl

Comment From: javierprovecho

@netroby hey, this works for me:

package main

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

func main() {
    r := gin.Default()
    r.LoadHTMLGlob("templates/*/*.html")

    r.GET("/", func(c *gin.Context) {
        c.SetCookie("user", "gin", 1, "/", "localhost", true, true)
        c.String(200, "hello")

    })

    r.DELETE("/del/:id", func(c *gin.Context) {
        c.String(200, "works")
    })

    r.PUT("/put/:id", func(c *gin.Context) {
        c.String(200, "works")
    })

    r.Run(":8080")
}
user@computer:~/Escritorio/go$ find
.
./main.go
./templates
./templates/dir1
./templates/dir1/21.html
./templates/dir1/1.html
./templates/dir1/2.html
./templates/dir2
./templates/dir2/6.html
./templates/dir2/3.html

user@computer:~/Escritorio/go$ go run main.go
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] Loaded HTML Templates (5): 
    - 6.html
    - 1.html
    - 2.html
    - 21.html
    - 3.html

[GIN-debug] GET   /                         --> main.func·001 (3 handlers)
[GIN-debug] DELETE /del/:par/id              --> main.func·002 (3 handlers)
[GIN-debug] PUT   /put                      --> main.func·003 (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080

there is any trace or panic giving you trouble, if so, can you post it?

Comment From: ghost

Really ? can you show me c.HTML usage templates location at subdirectory?

Comment From: javierprovecho

@netroby when you use r.LoadHTMLGlob("templates/*/*.html"), it looks for all unique filenames inside the expression. After that, you can call the template by its filename, like this: c.HTML(200, "21.html", gin.H{}).

There is a problem, that if two files share the same name in different directories, only one would be imported. But there is also a solution and derived from it, a good practice. Change the filenames of your templates, to something with an identifier as a prefix. This allows you to recognize easily which template are you using inside your source code.

Comment From: rafalbraun

@netroby The problem with this solution is that it requires rigid structure for placing files inside templates directory (no files allowed directly inside /templates, no nested folders inside allowed). I solved issue with this small piece of code loading templates recursively, hope it helps someone:

package main

import (
    "os"
    "github.com/gin-gonic/gin"
    "path/filepath"
    "net/http"
    "log"
)

func main() {

    router := gin.Default()

    // load templates recursively
    files, err := loadTemplates("templates")
    if err != nil {
        log.Println(err)
    }
    router.LoadHTMLFiles(files...)
    router.GET("/", func(c *gin.Context) {
        c.HTML(
            http.StatusOK,
            "index.html",
            gin.H{
                "title": "Home Page",
            },
        )
    })

    err = router.Run("localhost:8080")
    if err != nil {
        log.Fatalf("Http server crashed: " + err.Error())
    }
}

func loadTemplates(root string) (files []string, err error) {
    err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        fileInfo, err := os.Stat(path)
        if err != nil {
            return err
        }
        if fileInfo.IsDir() {
            if (path != root) {
                loadTemplates(path)
            }
        } else {
            files = append(files, path)
        }
        return err
    })
    return files, err
}