提供静态文件时出现golang错误

时间:2017-08-26 21:03:10

标签: go go-templates fileserver go-html-template gopath

执行模板时,我无法在go lang中找出此错误

panic: open templates/*.html: The system cannot find the path specified.

另一个问题是我的公共文件夹无法通过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指向包含project bin pkg

的文件夹src

当我在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服务

UPDATE ::

模板文件夹解决了第一个问题。

但我仍然无法解决第二个问题

1 个答案:

答案 0 :(得分:2)

我个人认为标准http库非常适合这些任务。但是,如果你坚持使用Gorilla&#39; 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返回使用http.HandleFunc的新templatesPath的原因。