如果请求是按值传递的,那么HTTP请求的值将为空。

huangapple go评论73阅读模式
英文:

http request values are empty if the request is passed by value

问题

这段代码是一个使用Go语言编写的简单程序。它创建了一个HTTP请求,并尝试从请求中获取名为"g-recaptcha-response"的表单值。

在第一个示例中,程序创建了一个HTTP请求,并将其作为值传递给Verify函数。然后,它尝试从请求中获取名为"z"的表单值,并打印出来。但是,由于请求是通过值传递的,所以在Verify函数中对请求的修改不会影响到main函数中的请求对象,因此打印出的结果为空。

在第二个示例中,程序在调用Verify函数之前先获取了请求中的"z"值,并打印出来。然后,它将请求作为值传递给Verify函数,并再次尝试获取"z"的值。这次打印出的结果是正确的,因为在调用Verify函数之前已经获取了请求中的值。

总结起来,如果将请求作为值传递给函数,对请求的修改不会影响到原始的请求对象。如果想要在函数中修改请求对象并影响到原始的请求,可以将请求作为指针传递给函数。

这个问题在不同版本的Go语言中都存在,无论是1.5还是1.7版本。如果将请求作为指针传递给函数,它会按预期工作。

英文:

Could someone explains what's happening here?

package main

import (
	"fmt"
	"net/http"
	"strings"
)

func Verify(req http.Request) string {
	return req.FormValue("g-recaptcha-response")
}

func main() {
	req, _ := http.NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not",
		strings.NewReader("z=post&both=y&prio=2&empty="))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
    Verify(*req)
	fmt.Println(req.FormValue("z"))
}

(https://play.golang.org/p/ve4Cc_JTzr)

This will produce an empty output.
Now if I access the value "z" before passing the request as value, it works!

package main

import (
	"fmt"
	"net/http"
	"strings"
)

func Verify(req http.Request) string {
	return req.FormValue("g-recaptcha-response")
}

func main() {
	req, _ := http.NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not",
		strings.NewReader("z=post&both=y&prio=2&empty="))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
    Verify(*req)
	fmt.Println(req.FormValue("z"))
}

(https://play.golang.org/p/5ALnt-pHTl)

I have tried with several versions of go from 1.5 to 1.7, with the same odd result.
If the request is passed by reference, it's working as expected.

答案1

得分: 5

这是因为请求的主体是io.Reader,而你只能从io.Reader中读取一次数据。当你尝试第二次读取内容时,就没有更多的数据可读取了。

FormValue方法调用了ParseForm,它会从读取器中读取所有的数据。

英文:

It's because Request's body is io.Reader, and you can read from io.Reader only once, when you try to read content second time, there is no more data to read.

Method FormValue calls ParseForm, and it reads all data from the reader.

huangapple
  • 本文由 发表于 2016年8月17日 03:35:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/38983089.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定