请求在Go中重新路由,映射句柄
我想将路径名映射到位于不同位置的文件。但是当我访问请求在Go中重新路由,映射句柄,go,gorequest,Go,Gorequest,我想将路径名映射到位于不同位置的文件。但是当我访问/a时,我的代码服务于/path/c.txt,而不是/path/a.txt。我做错了什么 package main import ( "fmt" "net/http" ) func main() { fileRoutes := map[string]string { "/a": "/path/a.txt", "/b": "/path/b.txt", "/c": "/pat
/a
时,我的代码服务于/path/c.txt
,而不是/path/a.txt
。我做错了什么
package main
import (
"fmt"
"net/http"
)
func main() {
fileRoutes := map[string]string {
"/a": "/path/a.txt",
"/b": "/path/b.txt",
"/c": "/path/c.txt",
}
for req, path := range fileRoutes {
http.HandleFunc(req, func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("actual request: %v\n", r.URL.Path)
fmt.Printf("registered request: %v\n", req)
r.URL.Path = path
fmt.Println(req)
fmt.Println(path)
// serveFile(w, r)
})
}
http.ListenAndServe(":8004", nil)
}
此示例代码生成:
actual request: /a
registered request: /c
/c
/path/c.txt
谢谢大家! 问题在于,所有句柄函数都在访问相同的
req
和path
,它们被设置为循环后的最后一个变量,即/c
和/path/c.txt
要解决此问题,请在http.HandleFunc(…)之前添加req,path:=req,path
这似乎很奇怪。它所做的是在循环范围内声明新的
req
和path
,这在每次迭代中都是新的,因此每个闭包绑定到不同的值。另一个解决方案就是这里使用的解决方案(感谢现在的答案,我已经理解了)::
path:=fileRoutes[req]
在http.HandleFunc
之前,或者将req
和path
声明为全局变量!(var-req-string
和var-path-string
开始循环之前)@DanielSchuette不,这不起作用。你自己试试,对我有用。当然,您必须用=
替换:=
,并在循环中重新分配一个临时变量。不过,我的回答可能会简短到足以说明这一点。这与您的解决方案也没有什么不同。@DanielSchuette所以您只需将for
语句中指定的内容提升到全局范围。重点是什么?我通常就是这样做的,特别是因为它看起来更干净。当然,这是基于意见的。我认为,如果使用另一个变量,其他人更容易理解为什么要在for循环中重新赋值。这只是另一种选择,这就是我写这篇评论的原因。