Go “放在哪里?”;延迟请求正文关闭();?

Go “放在哪里?”;延迟请求正文关闭();?,go,Go,我有net/http处理程序,在web服务器端的每个处理程序中都有defer req.Body.Close() // Body is the request's body. // // For client requests, a nil body means the request has no // body, such as a GET request. The HTTP Client's Transport // is responsible for calling the Cl

我有
net/http
处理程序,在web服务器端的每个处理程序中都有
defer req.Body.Close()

// Body is the request's body. 
// 
// For client requests, a nil body means the request has no 
// body, such as a GET request. The HTTP Client's Transport 
// is responsible for calling the Close method. 
// 
// For server requests, the Request Body is always non-nil 
// but will return EOF immediately when no body is present. 
// The Server will close the request body. The ServeHTTP 
// Handler does not need to. 
放这个的正确位置是什么?我应该把它放在函数的末尾还是很重要,我可以把它放在函数的开头?

根据Go,一旦你完成了它,你就可以关闭身体了

我通常将延迟行放在检查请求错误的行之后

放这个的正确位置是什么?我应该把它放在函数的末尾,还是它很重要,我可以把它放在函数的开头

既不是也不是。两者都大错特错

延迟请求Body.Close()
已成为邪教

首先是确凿的事实:

  • 如果请求失败(返回非nil错误),则不会以延迟方式或直接方式关闭主体

  • 必须关闭所有可能采用的代码路径上的正文(如果存在)

  • 您可能不希望在处理实体(或至少部分实体)之前关闭实体

  • 回到问题中的选项:

    • “在[函数的]开头”:完全错误,因为Body可能为零(事实1)

    • “在[函数的]结尾处”:完全错误,因为A)这是危险的,因为您可能会错过离开函数的代码路径(事实2)和B)即使您为所有函数结尾(即返回)配备了
      defer Bod.Close()
      延迟它,而不是简单地通过
      Body.Close()关闭它,也完全没有用


    延迟关闭请求正文的唯一合理方法是在确定正文为非零后立即关闭一次,这意味着请求没有返回错误。

    不需要在处理程序中关闭请求正文。从

    net/http
    服务器请求 在,
    net/http
    中阐明:

    对于服务器请求,请求主体始终为非nil,但在没有主体时将立即返回EOF。 服务器将关闭请求正文。ServeHTTP处理程序不需要这样做。
    正如文档中提到的,不需要在客户端和服务器端显式地关闭它

    // Body is the request's body. 
    // 
    // For client requests, a nil body means the request has no 
    // body, such as a GET request. The HTTP Client's Transport 
    // is responsible for calling the Close method. 
    // 
    // For server requests, the Request Body is always non-nil 
    // but will return EOF immediately when no body is present. 
    // The Server will close the request body. The ServeHTTP 
    // Handler does not need to. 
    

    如果将
    defer-req.Body.Close()
    放在末尾,则不需要使用
    defer
    关键字,但您或任何未来的程序员可能会意外地添加从函数早期返回的代码,然后
    req.Body.Close()
    将无法运行。这一点不重要/不清楚,但您是在询问位于服务器端的http.Handler服务传入请求的情况吗?或者作为客户机,向其他服务器发出HTTP请求?@JimB这就是答案,发布它。@icza:我想我会找到一个dup,但运气不好;)我将把它留在这里:
    对于服务器请求,请求主体总是非nil
    …这个答案只适用于“客户端”http请求。服务器端(如问题所述)不需要关闭。(但当应用于客户端时,您的答案是有用的)@DenisV,除非您正在测试控制器并创建自己的请求,但忽略了在请求中添加主体(即通过使用
    http.NewRequest(“某些方法”,“某些路径”,nil)
    )此答案仅适用于“客户端”http请求。服务器端(如问题所述)不需要关闭。