Go 1.16 is out and I want to use the new embed features. I can get it to work if everything is in the main package. But it's not clear how to handle accessing resources from subfolders/packages. Trying to do it with embed.FS support.
e.g. I have a main.go and also an HTTP handler in a handlers package/folder
If I put the handler in the main, it works. If I put it in the handlers package, it can't find the templates. I get:
handlers/indexHandler.go:11:12: pattern templates: no matching files found exit status 1
Similarly, I can get it to serve an image from the static folder if I serve it from /. But I can't serve both a handler from / and the static/images from /. If I put images on /static/ it can't find the images.
I think it has to do with relative paths. But I can't find the right combination through trial and error... Could it be too early to rely on these features?
Previously I was using go-rice and I did not have these problems. But I would like to use the std library as much as possible.
main.go:
package main
import (...)
//go:embed static
var static embed.FS
func main() {
fsRoot, _ := fs.Sub(static, "static")
fsStatic := http.FileServer(http.FS(fsRoot))
http.Handle("/", fsStatic)
http.HandleFunc("/index", Index)
http.ListenAndServe(":8080", nil)
}
handlers/indexHandler.go:
package handlers
import (...)
//go:embed templates
var templates embed.FS
// Index handler
func Index(w http.ResponseWriter, r *http.Request) {
tmpl := template.New("")
var err error
if tmpl, err = tmpl.ParseFS(templates, "simple.gohtml"); err != nil {
fmt.Println(err)
}
if err = tmpl.ExecuteTemplate(w, "simple", nil); err != nil {
log.Print(err)
}
}
Structure is as follows...
.
├── go.mod
├── go.sum
├── handlers
│ └── indexHandler.go
├── main.go
├── static
│ ├── css
│ │ └── layout.css
│ └── images
│ └── logo.png
└── templates
└── simple.gohtml
I finally figured it out...
You can keep the templates folder in the main folder and embed them from there. Then you need to inject the FS variable into the other handler package. It's always easy after you figure it out.
e.g.
package main
//go:embed templates/*
var templateFs embed.FS
func main() {
handlers.TemplateFs = templateFs
...
package handlers
var TemplateFs embed.FS
func handlerIndex() {
...
tmpl, err = tmpl.ParseFS(TemplateFs, "templates/layout.gohtml",...
...