我仍在学习如何使用Go进行Web开发,但当我试图创建一个简单的网站时,我面临着以下困难:
package main
import (
"fmt"
"html/template"
"net/http"
)
func main() {
fs := http.FileServer(http.Dir(""))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
tmpl, _ := template.ParseFiles("index.html")
tmpl.Execute(w, nil)
})
/**
* This route will return a 404 error
*/
http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Test page")
})
/**
* If I replace fs to nil, /test route will be work, but non-existent routes
* will be return index.html template (home router) instead 404 error. Why?
*/
http.ListenAndServe(":80", fs)
}
在http.FileServer
和http.HandleFunc
之间存在冲突。
例如,当我写:http.ListenAndServe(":80", nil)
,所有路由(http.HandleFunc
)都可以工作,但是如果我尝试这样做:http.ListenAndServe(":80", http. FileServer(http.Dir("")))
没有路由工作(http.HandleFunc("/"))
除外)。为什么?为什么?
如何访问404错误页面?我希望Go有一个像http.HandleError
这样的方法,它接受http.ResponseWriter
和http.Request
的接口,但我找不到任何类似的东西。
1条答案
按热度按时间j2cgzkjk1#
如果我将fs替换为nil,/test route将工作,但不存在的路由将返回index.html模板(家庭路由器)而不是404错误。为什么?为什么?
查看
http.ListenAndServe
的文档:func ListenAndServe(addr string, handler Handler) error
处理程序通常为nil,在这种情况下使用DefaultServeMux。
如果
handler
为nil,则将使用默认处理程序,而http.HandleFunc
:HandleFunc在DefaultServeMux中注册给定模式的处理程序函数。ServeMux的文档解释了如何匹配模式。
因此,在代码中,您使用
DefaultServeMux
注册了两个路由;调用http.ListenAndServe(":80", nil)
使用默认的处理程序(你添加了路由),所以/test
工作(下面有更多信息!但是,当你运行http.ListenAndServe(":80", fs)
时,你传递了一个特定的处理程序(fs
),所以所有的请求都会被发送到这个处理程序(它将尝试从你的本地文件系统提供文件)。从这一点开始,我将假设使用
http.ListenAndServe(":80", nil)
(因为添加处理程序然后不使用它们实际上没有意义)。上面提到的
ServeMux
让我们检查一下文档:模式命名固定的根路径,如“/favicon.ico”,或根子树,如“/images/”(注意结尾的斜杠)。较长的模式优先于较短的模式,因此,如果同时为“/images/”和“/images/thumbnails/"注册了处理程序,则后一个处理程序将被调用以“/images/thumbnails/”开头的路径,而前者将接收对“/images/”子树中任何其他路径的请求。
因此,Mux接收请求并计算出应该调用哪个处理程序来处理请求(注意,只会调用一个处理程序)。匹配是基于模式的长度(因此,在您的示例中,
/test
比/
长,因此优先选择)。这意味着对/test
的请求将触发fmt.Fprint(w, "Test page")
,其他所有请求将调用加载index.html
的处理程序。重要的是要注意,您没有添加引用fs
的处理程序,因此未使用它(并且代码将无法编译-playground)。希望这能解释正在发生的事情;在实现您想要的结果方面,以下是一些应该有所帮助的问题: