因此,问题在于您实际上使用了以下代码:
for _, path := range paths { http.HandleFunc(path, func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, path) })}您使用了函数文字(闭包)作为要注册的处理函数。闭包 捕获 它们所引用的上下文(在您的情况下为
pathloop变量)。
但是只有一个
path循环变量,其值在循环的每次迭代中都会被覆盖,并且其最终值将是最后一条路径。规范中的相关部分:对于带有
range子句的语句:
可以使用简短变量声明(
:=)的形式由“
range”子句声明迭代变量。在这种情况下,将它们的类型设置为各个迭代值的类型,并且它们的范围是“
for”语句的块; 它们在每次迭代中都会重复使用 。如果迭代变量在“ for”语句之外声明,则执行后它们的值将是上一次迭代的值。
一旦
for循环结束后,你开始做的请求,每个注册的处理函数将传回这个单一的数值
path变量。这就是为什么您看到为所有请求的路径返回的最后一个路径。
解决方案很简单:在每次迭代中创建一个新变量,并在处理函数中使用它:
for _, path := range paths { path2 := path http.HandleFunc(path2, func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, path2) })}这里发生的是,我们在每次迭代中都使用一个简短的变量声明来创建一个
新 变量,并使用
path循环变量的值对其进行初始化。我们注册的处理程序函数将引用此新变量,该变量仅对一个注册路径唯一。
另一个同样好的解决方案是使用带有参数的匿名函数来传递
path字符串。但是可能更难理解:
for _, path := range paths { func(p string) { http.HandleFunc(p, func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, p) }) }(path)}这里发生的是,我们调用一个匿名函数,将当前
path值传递给它,然后仅使用该匿名函数的参数注册处理程序函数(并且为每个调用分配了一个新的,不同的局部变量)。



