在Go HTTP处理程序中,为什么ResponseWriter是一个值,但Request是一个指针?

Sud*_*han 72 pointers go

我正在通过为GAE编写应用程序来学习Go,这是处理函数的签名:

func handle(w http.ResponseWriter, r *http.Request) {}
Run Code Online (Sandbox Code Playgroud)

我是指针新手,所以为什么Request对象是一个指针,但ResponseWriter不是?有没有必要这样做或者这只是为了使某种基于高级指针的代码成为可能?

Den*_*ret 56

你得到的w是一个指向非导出类型的指针,http.response但是ResponseWriter一个接口,它是不可见的.

来自server.go:

type ResponseWriter interface {
    ...
}
Run Code Online (Sandbox Code Playgroud)

另一方面,r是一个指向具体结构的指针,因此需要明确地确定它:

来自request.go:

type Request struct {
    ...
}
Run Code Online (Sandbox Code Playgroud)


nos*_*nos 27

http.ResponseWriter是一个接口,实现此接口的现有类型是指针.这意味着不需要使用指向此接口的指针,因为它已经被指针"支持".这个概念是描述一个有点旅途develpers之一这里虽然类型实现http.ResponseWriter并不需要是一个指针,它不会是实用的,至少不是去http服务器内.

http.Request它不是一个接口,它只是一个结构,因为我们想要更改这个结构并让Web服务器看到这些更改,它必须是一个指针.如果它只是一个struct值,我们只需修改一个调用我们的代码的Web服务器看不到它的副本.

  • 好吧,我并不是说暗示_all_实现接口的东西必须是指针.类似于ResponseWriter的东西,需要修改接口后面的值的状态来做任何有用的事情,并且这将要求值是指针类型(正如我链接到的博客文章所说).但是,http.ResponseWriter理论上可以通过int实现(其方法永远不会改变该int值). (2认同)

joa*_*kim 12

正如此处和其他地方的许多其他答案中正确提到的那样,ResponseWriter是一个界面,其含义已在SO答案和博客中详细描述。

我想解决的是,我觉得这里有一个大而危险的误解,请求通过“引用”传递的原因(尽管在Go中并不真正存在这样的事情)是“我们想要进行更改它对服务器可见”。

引用几个答案:

[..]它只是一个结构,因为我们想改变这个结构,并在Web服务器看到这些变化,它必须是一个指针[..] SO

[..]被处理的更改需要请求中可见的服务器,所以我们只能通过它通过引用而不是值[..] SO

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

除了读取正文之外,处理程序不应修改提供的请求。

恰恰相反,不是吗?:-)

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

Go 团队已提出更改行为以允许修改传入请求的请求,但更改此类内容可能至少会导致某些现有代码意外中断。

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

  • 这是我终于明白的答案。 (2认同)