为什么请求是一个指针变量?为什么不是一个引用变量?

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

Why the request is a pointer variable? Why not a reference variable?

问题

我现在已经学习GO语言一个月了。我已经用Java编程超过4年了。在Java中,请求(Request)和响应(Response)都是对象引用。但是,在Go语言中,响应(Response)是一个对象引用,而请求(Request)是一个指针引用。

引用(reference)和指针(pointer)一样,都是可以间接引用另一个对象的对象。引用声明的语法结构与指针声明基本相同。

除了可读性和语法糖之外,使用请求(Request)作为指针变量还有其他意图吗?

补充上面的问题,这里的请求(Request)是一个任意指针。也就是说,请求(Request)尚不存在,但指针已经引用了一个内存位置。如果我理解有误,请给予一些解释。

英文:

I have been learning GO Lang for a month now. I have been coding in java for more than 4 years. In java the Request and Response both are object references. But, when it comes to GoLang the Response is a object reference and the Request is a Pointer Reference.

A reference, like a pointer, is an object that you can use to refer indirectly to another object. A reference declaration has essentially the same syntactic structure as a pointer declaration.

func hello(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Hello world!")
}

Apart from the readability perspective and the syntactic sugar is there any other intention behind using the Request as a pointer variable.

Adding to the above question the request here is an arbitrary pointer. i.e the request is not yet exists but the pointer is already referring to a memory location. Please throw some light if my understanding is wrong.

答案1

得分: 2

正如其他答案和博客中正确提到的那样,ResponseWriter 是一个接口,关于这一点的影响已经在 SO 的答案和博客中详细描述过。

我想要解释的是我认为这里存在的一个重大且危险的误解,即请求被以“引用”的方式传递(虽然在 Go 中实际上并不存在这样的概念)是因为“我们希望对其进行的更改对服务器可见”。

引用其他人的几个答案:

> [..]它只是一个结构体,由于我们希望更改此结构体并使 Web 服务器看到这些更改,所以它必须是一个指针[..] SO
>
> [..]处理程序对请求的更改需要对服务器可见,因此我们只传递引用而不是值[..] SO

这是错误的;事实上,文档明确警告不要篡改/修改请求

> 除了读取 body 外,处理程序不应修改提供的 Request。

恰恰相反,不是吗? 为什么请求是一个指针变量?为什么不是一个引用变量?

如果你想要更改请求,例如在将其传递给中间件链中的下一个处理程序之前附加一个跟踪标头,你必须复制该请求并将复制的版本传递给链中的下一个处理程序。

如果我们明确告诉人们不要修改请求,为什么要使用指针?性能Request 是一个大的结构体,复制它可能会降低性能,特别是考虑到长的中间件链。团队必须在性能和 API 安全之间取得平衡,这绝不是一个理想的解决方案,但在这里权衡明显是为了性能(而不是 API 安全)。

英文:

As correctly mentioned in many other answers here and elsewhere, ResponseWriter is an interface and the implications of this have beed described in detail in SO answers and blogs.

What I would like to address is what I feel is the big—and dangerous—misconception here, that the reason request is passed by "reference" (although such a thing does not really exist in Go) is that "we want to make changes to it visible to the server".

Quoting a couple of answers from other people:

> [..]it's just a struct, and since we want to change this struct and have the web server see those changes, it has to be a pointer[..] SO
>
> [..]changes to Request by the handler need to be visible to the server, so we’re only passing it by reference instead of by value [..] SO

This is wrong; in fact the docs explicitly warn against tampering with / mutating the request:

> Except for reading the body, handlers should not modify the provided Request.

Quite the opposite, no? 为什么请求是一个指针变量?为什么不是一个引用变量?

If you want to change the request, e.g. append a tracing header before passing it on to the next handler in a middleware chain you have to copy the request and pass the copied version down the chain.

Why use a pointer if we are explicitly telling people not to mutate the request? Performance, Request is a large struct and copying it can bring performance down, especially with long middleware chains in mind. The team had to strike a balance, definitely not an ideal solution, but the tradeoffs are clearly on the side of performance here (instead of API safety).

答案2

得分: 1

这是一个关于Go语言中的HTTP处理程序的问题。主要问题是为什么ResponseWriter是一个值类型,而Request是一个指针类型。

主要原因是ResponseWriter是一个接口类型,你可能需要更多了解接口的知识(以防你还没有学习过)。另外,请求是一个指向结构体的指针类型,没有必要复制请求结构体(当按值传递时会发生复制),所以它不是作为结构体传递的(尤其是当你将其直接传递给其他函数时,请考虑这一点)。

英文:

Duplicate of https://stackoverflow.com/questions/13255907/in-go-http-handlers-why-is-the-responsewriter-a-value-but-the-request-a-pointer

Mainly the ResponseWriter is an interface (you may want to understand more about interfaces, just in case you haven't gone over it). Just to add, the request is a pointer to a struct - there's no point in having a copy of the request struct (which happens when passed by value), so it's not passed as a struct (think of it esp. when you pass it downstream to other functions, you can just pass this down directly)

huangapple
  • 本文由 发表于 2017年6月13日 12:45:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/44512567.html
匿名

发表评论

匿名网友

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

确定