英文:
golang error when serving static files
问题
我无法解决这个在执行模板时出现的Go语言错误:
panic: open templates/*.html: 系统找不到指定的路径。
另一个问题是我的public文件夹无法提供css文件,我不知道为什么。
代码:
package main
import (
"net/http"
"github.com/gorilla/mux"
"html/template"
"log"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.html"))
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/",home)
http.Handle("/public/", http.StripPrefix("/public/",
http.FileServer(http.Dir("/pub"))))
http.ListenAndServe(":8080", r)
}
func home(writer http.ResponseWriter, request *http.Request) {
err := tpl.ExecuteTemplate(writer, "index.html", nil)
if err != nil {
log.Println(err)
http.Error(writer, "Internal server error", http.StatusInternalServerError)
}
}
我的文件夹结构如下:
bin pkg pub css home.css js src github.com gorila/mux templates index.html
我的GOROOT指向包含bin
、pkg
和src
文件夹的project
文件夹。
当我将templates
文件夹放在src
之外时,它可以正常工作,但我认为这不正确,一切都应该在src
中,对吗?
index.html文件内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<link href="../public/css/home.css" type="text/css" rel="stylesheet" />
</head>
<body>
<h1>welcome! hi</h1>
</body>
</html>
在这里,我无法提供css文件。
更新:
第一个问题已解决,关于templates文件夹的问题。
但是我仍然无法解决第二个问题。
英文:
I can't figure out this error in go lang when executing a template
panic: open templates/*.html: The system cannot find the path specified.
another problem is that my public folder can't be served from css and I don't know why.
code:
package main
import (
"net/http"
"github.com/gorilla/mux"
"html/template"
"log"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.html"))
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/",home)
http.Handle("/public/", http.StripPrefix("/public/",
http.FileServer(http.Dir("/pub"))))
http.ListenAndServe(":8080", r)
}
func home(writer http.ResponseWriter, request *http.Request) {
err := tpl.ExecuteTemplate(writer, "index.html", nil)
if err != nil {
log.Println(err)
http.Error(writer, "Internal server error", http.StatusInternalServerError)
}
}
my folder is like that:
<pre>bin
pkg
pub
css
home.css
js
src
github.com
gorila/mux
templates
index.html</pre>
my GOROOT is pointing to the folder project
which contains the bin
pkg
src
when I make the templates
folder outside src
it works fine but I thinks that's not right everything must be in src
right ?
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<link href="../public/css/home.css" type="text/css" rel="stylesheet" />
</head>
<body>
<h1>welcome! hi</h1>
</body>
</html>
here i can't serve the css
UPDATE::
the first problem is solved of the templates folder .
but I am still cannot solve the second issue
答案1
得分: 3
我个人认为标准的http
库非常适合这种任务,简单易用。不过,如果你坚持使用Gorilla的mux
,我在你的代码中找到了一个问题:
func main() {
...
http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("/pub"))))
http.ListenAndServe(":8080", r)
}
一方面,你在使用http.Handle
来提供静态文件,但另一方面你将r
传递给了http.ListenAndServe
。
要修复这个问题,只需将那一行改为:
r.PathPrefix("/public/").Handler(
http.StripPrefix("/public/",
http.FileServer(http.Dir("/pub/"))))
如果可以的话,我建议使用flag
来设置模板目录和公共目录的不同路径,这样可以轻松部署和运行服务器。
换句话说,不要硬编码这些目录的路径,可以运行:
./myserver -templates=/loca/templates -public=/home/root/public
只需添加以下内容:
import "flag"
....
func main() {
var tpl *template.Template
var templatesPath, publicPath string
flag.StringVar(&templatesPath, "templates", "./templates", "Path to templates")
flag.StringVar(&publicPath, "public", "./public", "Path to public")
flag.Parse()
tpl = template.Must(template.ParseGlob(templatesPath+"/*.html"))
r.HandleFunc("/", handlerHomeTemplates(tpl))
r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir(publicPath))))
...
}
func handlerHomeTemplates(tpl *template.Template) http.HandlerFunc {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
err := tpl.ExecuteTemplate(writer, "index.html", nil)
if err != nil {
...
}
})
}
虽然init
函数是做这部分工作的好地方,但我认为除非必要,最好避免使用它。这就是为什么我在main
函数中进行了所有的初始化,并使用handlerHomeTemplates
返回一个使用templatesPath
的新http.HandleFunc
的好做法。
英文:
I personally find the standard http
library very good and simple for such tasks. However, if you insist on Gorilla's mux
here is the problem I found in your code:
func main() {
...
http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("/pub"))))
http.ListenAndServe(":8080", r)
}
On one hand you are using http.Handle
to serve static files but on the other hand you're giving r
to http.ListenAndServe
.
To fix this just change that line into:
r.PathPrefix("/public/").Handler(
http.StripPrefix("/public/",
http.FileServer(http.Dir("/pub/"))))
If I may, I would like to suggest using flag
to set a different path to the templates directory and to the public directory so it would be easy to deploy and run your server.
In other words, instead of hardcoding the path to these directories you can run:
./myserver -templates=/loca/templates -public=/home/root/public
To do that just add the following:
import "flag"
....
func main() {
var tpl *template.Template
var templatesPath, publicPath string
flag.StringVar(&templatesPath, "templates", "./templates", "Path to templates")
flag.StringVar(&publicPath, "public", "./public", "Path to public")
flag.Parse()
tpl = template.Must(template.ParseGlob(templatesPath+"/*.html"))
r.HandleFunc("/", handlerHomeTemplates(tpl))
r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir(publicPath))))
...
}
func handlerHomeTemplates(tpl *template.Template) http.HandlerFunc {
return http.HandlerFunc(func((writer http.ResponseWriter, request *http.Request) {
err := tpl.ExecuteTemplate(writer, "index.html", nil)
if err != nil {
...
}
})
}
Even thought the init
function is a good place to do part of it, I think it's a good practice to avoid it unless it's needed. That's why I did all the initialization in the main
function and used handlerHomeTemplates
to return a new http.HandleFunc
that uses templatesPath
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论