8

I want to specify an html template in one of my golang controller My directory structure is like this

 Project
 -com
  -src
   - controller
     -contoller.go
 -view
  - html
   -first.html

I want to load first.html for request /new .I have used NewHandler for url /new and the NewHandler func is executing when /new request comes and is in controller.go. Here is my code

func NewHandler(w http.ResponseWriter, r *http.Request) {
    t, err := template.ParseFiles("view/html/first.html")
    if err == nil {
        log.Println("Template parsed successfully....")
    }
 err := templates.ExecuteTemplate(w, "view/html/first.html", nil)
if err != nil {
    log.Println("Not Found template")
}
//  t.Execute(w, "")
}

But I am getting an error

     panic: open first.html: no such file or directory

Please help me to remove this error. Thanks in advance

Akhil Sudhakaran
  • 357
  • 2
  • 3
  • 12
  • Possible duplicate of [How to use go template to parse html files with FuncMap](http://stackoverflow.com/questions/34058772/how-to-use-go-template-to-parse-html-files-with-funcmap) and [404 page not found - Go rendering css file](http://stackoverflow.com/questions/28293452/404-page-not-found-go-rendering-css-file); also related: [how to reference a relative file from code and tests](http://stackoverflow.com/questions/31059023/how-to-reference-a-relative-file-from-code-and-tests) – icza Jul 07 '16 at 07:06

4 Answers4

9

I have solved the issue by giving absolute path of the html. For that I created a class in which the html are parsed

package htmltemplates

import (
"html/template"
"path/filepath"
)

And in the NewHandler method I removed //Templates is used to store all Templates var Templates *template.Template

func init() {
filePrefix, _ := filepath.Abs("./work/src/Project/view/html/")       // path from the working directory
Templates = template.Must(template.ParseFiles(filePrefix + "/first.html")) 
...
//htmls must be specified here to parse it
}

And in the NewHandler I removed first 5 lines and instead gave

err := htmltemplates.Templates.ExecuteTemplate(w, "first.html", nil)

It is now working .But need a better solution if any

Akhil Sudhakaran
  • 357
  • 2
  • 3
  • 12
1

Have you included this line in the main function?

http.Handle("/view/", http.StripPrefix("/view/", http.FileServer(http.Dir("view"))))

view is the name of the directory that has to be specified in FileServer function to allow read/write.(view directory has to be kept in the same directory where your binary is present)

Michael Dorner
  • 17,587
  • 13
  • 87
  • 117
ganesh kumar
  • 146
  • 2
  • 7
  • yes. router.Handle("/", http.FileServer(http.Dir("./view/"))) – Akhil Sudhakaran Jul 07 '16 at 07:36
  • router is a mux router – Akhil Sudhakaran Jul 07 '16 at 07:37
  • issue solved by giving absolute path. But need a better solution ,if any – Akhil Sudhakaran Jul 07 '16 at 07:54
  • @AkhilSudhakaran Here are your options if you don't want to use absolute path: [options](http://stackoverflow.com/a/31059125/1705598) – icza Jul 07 '16 at 08:33
  • I have been using relative path only and it works fine. The problem must be in accessing the directory only(like /view or ./view etc). You can check by : Start the server, then try to access the view folder from browser, e.g typing localhost:8080/view should show the list of files available. Thanks @icza, good alternatives. – ganesh kumar Jul 07 '16 at 08:48
0

Better solution is to give absolute path name i.e instead of this "view/html/first.html",try this

 func NewHandler(w http.ResponseWriter, r *http.Request) {
        t, err := template.ParseFiles("./work/src/Project/view/html/first.html")
        if err == nil {
            log.Println("Template parsed successfully....")
        }
     err := templates.ExecuteTemplate(w, "view/html/first.html", nil)
    if err != nil {
        log.Println("Not Found template")
    }
    //  t.Execute(w, "")
    }
Nikta Jn
  • 346
  • 3
  • 7
0

Solution, where I just traversed outside the directory without using libraries to find the path or convert them.

  1. Using "os" package get the present working directory. Like, import( "os" ) your_function(){ pwd,_ := os.pwd()}

  2. Above snippet will return you the path where your program is trying to find the file. Like D:\Golang_Projects\POC\Distributed_Application_Go\cmd\teacherportal

  3. After you're sure what path your program is looking at, use ".." to come outside of that directory. Like,

    rootTemplate,err := template.ParseFiles("../../teacherportal/students.gohtml")

Alternative solutions are also there but I found this quite simple to implement.

infiniteLearner
  • 3,555
  • 2
  • 23
  • 32