Reputation: 859
For parsing files i have setup a variable for template.ParseFiles and i currently have to manually set each file.
Two things:
How would i be able to walk through a main folder and a multitude of subfolders and automatically add them to ParseFiles so i dont have to manually add each file individually?
How would i be able to call a file with the same name in a subfolder because currently I get an error at runtime if i add same name file in ParseFiles.
var templates = template.Must(template.ParseFiles(
"index.html", // main file
"subfolder/index.html" // subfolder with same filename errors on runtime
"includes/header.html", "includes/footer.html",
))
func main() {
// Walk and ParseFiles
filepath.Walk("files", func(path string, info os.FileInfo, err error) {
if !info.IsDir() {
// Add path to ParseFiles
}
return
})
http.HandleFunc("/", home)
http.ListenAndServe(":8080", nil)
}
func home(w http.ResponseWriter, r *http.Request) {
render(w, "index.html")
}
func render(w http.ResponseWriter, tmpl string) {
err := templates.ExecuteTemplate(w, tmpl, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
Upvotes: 2
Views: 5112
Reputation: 859
So basically i set New("path name i want").Parse("String from read file") while walking through the folders.
var templates = template.New("temp")
func main() {
// Walk and ParseFiles
parseFiles()
http.HandleFunc("/", home)
http.ListenAndServe(":8080", nil)
}
//////////////////////
// Handle Functions //
//////////////////////
func home(w http.ResponseWriter, r *http.Request) {
render(w, "index.html")
render(w, "subfolder/index.html")
}
////////////////////////
// Reusable functions //
////////////////////////
func parseFiles() {
filepath.Walk("files", func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
filetext, err := ioutil.ReadFile(path)
if err != nil {
return err
}
text := string(filetext)
templates.New(path).Parse(text)
}
return nil
})
}
func render(w http.ResponseWriter, tmpl string) {
err := templates.ExecuteTemplate(w, tmpl, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
Upvotes: 0
Reputation: 25275
To walk a directory looking for files see: http://golang.org/pkg/path/filepath/#Walk or http://golang.org/pkg/html/template/#New and http://golang.org/pkg/html/template/#Template.Parse
As for your other question ParseFiles uses the base name of the file as the template name which results in a collision in your template. You have two choices
t := template.New("name of your choice")
to create an initial template
t.Parse("text from file")
for each template file. You'll have to open and read the contents of the template files yourself to pass in here.Edit: Code example.
func main() {
// Walk and ParseFiles
t = template.New("my template name")
filepath.Walk("files", func(path string, info os.FileInfo, err error) {
if !info.IsDir() {
// Add path to ParseFiles
content := ""
// read the file into content here
t.Parse(content)
}
return
})
http.HandleFunc("/", home)
http.ListenAndServe(":8080", nil)
}
Upvotes: 4