英文:
http.ServeMux route mounting?
问题
让我们来看一下以下的代码模式:
package main
import (
"fmt"
"net/http"
)
func main() {
admin := http.NewServeMux()
admin.HandleFunc("/", root)
admin.HandleFunc("/foo", foo)
http.Handle("/admin", admin)
http.ListenAndServe(":4567", nil)
}
func root(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Admin: ROOT")
}
func foo(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Admin: FOO")
}
当我运行/admin
时,为什么它会触发root
处理程序,但当我运行/admin/foo
时却不会触发呢?只是为了明确,我不是在寻找替代的包,我实际上有一个自定义的路由器,我只是对这里发生的事情感到好奇,因为这个模式对我来说并不太合理。
英文:
Let's take the following pattern:
package main
import (
"fmt"
"net/http"
)
func main() {
admin := http.NewServeMux()
admin.HandleFunc("/", root)
admin.HandleFunc("/foo", foo)
http.Handle("/admin", admin)
http.ListenAndServe(":4567", nil)
}
func root(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Admin: ROOT")
}
func foo(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Admin: FOO")
}
How is it that when I run /admin
, it will fire the root handler, but when I run /admin/foo
it won't? Just to be clear, I'm not looking for an alternative package, I actually have a custom router, I'm just generally curious to what's going on here as this pattern isn't making much sense to me.
答案1
得分: 1
像@DewyBroto所说的那样,在子mux中你必须使用完整的路径。
你可以创建一个类似这样的包装器:
func NewChildMux(prefix string, vars ...interface{}) *http.ServeMux {
sm := http.NewServeMux()
for i := 0; i < len(vars); i += 2 {
path := prefix + vars[i].(string)
sm.HandleFunc(path, vars[i+1].(func(http.ResponseWriter, *http.Request)))
}
return sm
}
func main() {
admin := NewChildMux("/admin",
"/", root,
"/foo/", foo,
)
http.Handle("/admin/", admin)
http.ListenAndServe(":4567", nil)
}
英文:
Like @DewyBroto said, you have to use the full path in the child mux.
You could make a wrapper like this:
func NewChildMux(prefix string, vars ...interface{}) *http.ServeMux {
sm := http.NewServeMux()
for i := 0; i < len(vars); i += 2 {
path := prefix + vars[i].(string)
sm.HandleFunc(path, vars[i+1].(func(http.ResponseWriter, *http.Request)))
}
return sm
}
func main() {
admin := NewChildMux("/admin",
"/", root,
"/foo/", foo,
)
http.Handle("/admin/", admin)
http.ListenAndServe(":4567", nil)
}
答案2
得分: 1
请尝试以下代码:
func main() {
admin := http.NewServeMux()
// 使用挂载点作为所有路径的前缀。即使从另一个 ServeMux 调用,ServeMux 也会匹配完整路径。
mountPoint := "/admin"
admin.HandleFunc(mountPoint, root)
admin.HandleFunc(mountPoint + "/foo", foo)
// 在挂载点后添加斜杠以指示子树匹配。
http.Handle(mountPoint + "/", admin)
http.ListenAndServe(":4567", nil)
}
这段代码是一个简单的 Go 语言示例,用于创建一个 HTTP 服务器。它使用了 http
包中的 ServeMux
类型来处理不同的请求路径。在这个示例中,我们创建了一个名为 admin
的 ServeMux
实例,并将其挂载在 /admin
路径下。然后,我们使用 HandleFunc
方法将处理函数与路径关联起来。最后,我们使用 ListenAndServe
方法启动服务器并监听端口 4567
。
英文:
Try the following:
func main() {
admin := http.NewServeMux()
// Prefix all paths with the mount point. A ServeMux matches
// the full path, even when invoked from another ServeMux.
mountPoint := "/admin"
admin.HandleFunc(mountPoint, root)
admin.HandleFunc(mountPoint + "/foo", foo)
// Add a trailing "/" to the mount point to indicate a subtree match.
http.Handle(mountPoint + "/", admin)
http.ListenAndServe(":4567", nil)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论