How can use both LoadHTMLGlob and LoadHTMLFiles

Viewed 1747

I want separator logical template from difference subdirectories under templates folder, the following is my templates folder

templates
├── authentication
│   ├── login.gohtml
│   └── logout.gohtml
├── index.gohtml
└── profile
    └── userinfo.gohtml

Here is main.go


package main

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

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

    // router.Use(Threshold())   // not finished yet
    router.Use(Cors())

    // load templates
    // router.LoadHTMLGlob("templates/authentication/*.gohtml")
    router.LoadHTMLGlob("./templates/*/*.gohtml")
    router.LoadHTMLGlob("./templates/*.gohtml")
    // set static folder
    router.Static("/static", "./public")

    // handler the favicon.ico
    router.StaticFile("/favicon.ico", "./public/images/favicon.ico")


    InjectRoutes(router)



    // run the server at default port 8080
    router.Run(":8080")
}

InjectRoutes come from route.go

package main

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

    auth "github.com/yangwawa0323/mywebapp/v2/authentication"
    "github.com/yangwawa0323/mywebapp/v2/profile"
)

// Route struct
type Route struct {
    path         string
    handler      gin.HandlerFunc
    method       string
    templateFile interface{}
}

// R is alias of `Route`
type R = Route

// GenerateRoutes generate all the routes.
func GenerateRoutes() []Route {
    return []Route{
        R{"/", HomePage, "GET", "./templates/index.gohtml"},
        R{"/login", auth.Login, "GET", nil},
        R{"/logout", auth.Logout, "GET", nil},

        R{"/profile/:user/", profile.UserInfo, "GET", nil},
    }
}

// InjectRoutes function inject routes to gin.Engine
func InjectRoutes(router *gin.Engine) {
    for _, r := range GenerateRoutes() {
        if r.templateFile != nil {
            router.LoadHTMLFiles(r.templateFile.(string))
        }
        switch r.method {
        case "POST":
            router.POST(r.path, r.handler)
        case "DELETE":
            router.DELETE(r.path, r.handler)
        case "PUT":
            router.PUT(r.path, r.handler)
        default:
            router.GET(r.path, r.handler)
        }
    }
}


Here is debug message

[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 (4): 
    - 
    - login.gohtml
    - logout.gohtml
    - userinfo.gohtml

[GIN-debug] Loaded HTML Templates (2): 
    - index.gohtml
    - 

2021/01/03 10:02:34 http: panic serving [::1]:50590: html/template: "userinfo.gohtml" is undefined
goroutine 34 [running]:
net/http.(*conn).serve.func1(0xc000302000)
    /usr/lib/go-1.13/src/net/http/

As you can see that there are loaded the templates , but LoadHTMLGlod and LoadHTMLFiles only one is working, the lastest has precedence which overrided the previous one.

My question is how to wrote the glob to implement my requirement or has the other skill to wrote the code , I don't want make a new directory and put the index.gohtml in it, even it's working ? Thanks.

1 Answers

LoadHTMLGlob("path_patren") It cannot match all of your file paths. Because your files are stored at different depths. And not at same depth. See the documentation of filepath.Glob. For details.

As you know: Recalling loadHTMLGlob() does not solve the problem. You are actually resetting the template again and clearing the setting that you got on the first call to the function. The solution is simple. just remove loadHTMLGlob and write all pathFiles in LoadHTMLFiles. like this :


files := []string{
    "home.html", "acount.html", "login.html", "sign.html",
    "folder1/stores.html", "folder1/mystore.html", "folder1/upload.html",
    "folder2/templs/products.html", "foleder2/partial/header.html", "tmpl/partial/footer.html"}
    
templ := &Template{templates: template.Must(template.ParseFiles(files...))}

in gin : use LoadHTMLFiles(files...).

Related