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

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

func handle(w http.ResponseWriter, r *http.Request) {}

我在这里是指针新手,那么为什么该Request对象是指针,但ResponseWriter不是呢?是否有必要采用这种方式,或者仅仅是为了使某种基于高级指针的代码成为可能?


蓝山帝景
浏览 543回答 3
3回答

潇潇雨雨

您得到的w是指向非导出类型的指针,http.response但与ResponseWriter接口一样,这是不可见的。从server.go:type ResponseWriter interface {     ...}另一方面,r它是指向具体结构的指针,因此需要显式传递引用。从request.go:type Request struct {     ...}

智慧大石

该http.ResponseWriter是一个接口,并实现此接口的现有类型的指针。这意味着不需要使用指向该接口的指针,因为它已经由指针“支持”。这个概念是由go develpers的一个描述了一下这里虽然类型实现http.ResponseWriter并不需要是一个指针,它不实用,至少去http服务器之内。http.Request不是一个接口,它只是一个结构,并且由于我们要更改此结构并使Web服务器看到这些更改,因此它必须是一个指针。如果只是一个struct值,我们将修改它的副本,而调用我们的代码的Web服务器看不到它。

qq_花开花谢_0

正如此处和其他地方的许多其他答案中正确提到的那样,它ResponseWriter是一个界面,其含义已在SO答案和博客中进行了详细描述。我要解决的是我的感觉,这是一个巨大且危险的误解,原因是请求是通过“引用”传递的(尽管这样的事情在Go中实际上并不存在)是“我们想要进行更改使其对服务器可见”。引用几个答案:[..]它只是一个结构,因为我们想改变这个结构,并在Web服务器看到这些变化,它必须是一个指针[..] SO[..]处理程序对Request的更改需要对服务器可见,因此我们仅通过引用而不是通过值来传递[..] SO这是错误的; 实际上,文档明确警告不要篡改/更改请求:除读取正文外,处理程序不应修改提供的请求。相反,不是吗?:-)如果要更改请求,例如在将跟踪标头传递给中间件链中的下一个处理程序之前附加跟踪标头,则必须复制请求并将复制的版本向下传递给链。Go团队提出了更改行为以允许修改传入请求的请求,但更改此类内容可能会导致至少某些现有代码意外中断。如果我们明确告诉人们不要更改请求,为什么还要使用指针?性能,Request是一个大的结构,并复制它可以带来性能的下降,尤其是在考虑长期中间件链。团队必须权衡利弊,这绝对不是理想的解决方案,但是这里的权衡显然是性能方面的问题(而不是API安全性)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go