请求在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循环中重新赋值。这只是另一种选择,这就是我写这篇评论的原因。