-1

执行模板时我无法在 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)
    }
}

我的文件夹是这样的:

斌
包
酒馆
   css
     主页.css
   js
源代码
   github.com
        大猩猩/多路复用器
模板
        索引.html

我的 GOROOT 指向project包含bin pkg src

当我在templates外面制作文件夹时src,它工作正常,但我认为这不对,一切都必须src正确?

索引.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

更新::

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

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

4

1 回答 1

2

对于此类任务,我个人认为标准http库非常好且简单。但是,如果您坚持使用 Gorilla,那么mux我在您的代码中发现的问题是:

func main() {
    ...
    http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("/pub"))))
    http.ListenAndServe(":8080", r)
}

一方面您http.Handle用于提供静态文件,但另一方面您提供rhttp.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.

于 2017-08-27T09:26:18.870 回答