我想将路径名映射到位于其他位置的文件。但是,当我访问/path/c.txt
而不是/a
时,我的代码将服务/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
谢谢!
答案 0 :(得分:3)
问题在于,所有句柄函数都访问相同的req
和path
,它们被设置为循环后循环的最后一个变量,分别为/c
和{{ 1}}。
要解决此问题,请在/path/c.txt
之前添加req,path := req,path
。
似乎很奇怪。它的作用是在循环范围内声明新的http.HandleFunc(...)
和req
,这在每次迭代中都是新的,因此每个闭包都绑定到不同的值。
答案 1 :(得分:0)
另一种解决方案将是这里使用的解决方案(感谢我现在对答案的理解):https://github.com/golang/blog/blob/master/rewrite.go:
path := fileRoutes[req]
之前 http.HandleFunc