我如何在Golang中覆盖404

vlurs2pr  于 2023-10-14  发布在  Go
关注(0)|答案(1)|浏览(106)

我仍在学习如何使用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.FileServerhttp.HandleFunc之间存在冲突。
例如,当我写:http.ListenAndServe(":80", nil),所有路由(http.HandleFunc)都可以工作,但是如果我尝试这样做:
http.ListenAndServe(":80", http. FileServer(http.Dir("")))
没有路由工作(http.HandleFunc("/"))除外)。为什么?为什么?
如何访问404错误页面?我希望Go有一个像http.HandleError这样的方法,它接受http.ResponseWriterhttp.Request的接口,但我找不到任何类似的东西。

j2cgzkjk

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)。
希望这能解释正在发生的事情;在实现您想要的结果方面,以下是一些应该有所帮助的问题:

相关问题