golang 표준 라 이브 러 리 http 의 client 는 왜 resp. Body 를 수 동 으로 닫 아야 합 니까?

3109 단어 golang
golang http client 요청 을 사용 합 니 다. 저 희 는 보통 이렇게 합 니 다.
resp, err := http.Get(...)
if err != nil {
..
}
defer resp.Body.Close()

왜 꼭 resp.Body.Close() 해 야 합 니까?이 질문 에 대답 하려 면 사실 두 가지 질문 에 대답 해 야 한다.
  • resp.Body.Close() 뭐 했 어 요?
  • 왜 그 랬 어 요?

  • 1 resp.Body.Close() 뭐 했 어 요?
    Close 방법 이 무엇 을 했 는 지 확인 하기 위해 서 는 resp.Body 구체 적 으로 어떻게 이 루어 졌 는 지 확인 해 야 한다.http client 가 timeout 을 설정 할 지 여 부 는 resp.Body 의 두 가지 실현 을 결정 합 니 다. 첫째, timeout 을 설정 합 니 다.
    cli := http.Client{Timeout: time.Second}
    resp, _ := cli.Get(...)
    

    이 경우 resp.BodycancelTimerBody 두 번 째 로 timeout 을 설치 하지 않 는 경우 resp.BodybodyEOFSignal그런 경우 에 도 불구 하고 이 두 가지 body 는 결국 봉 인 된 이 body 입 니 다.
    // body turns a Reader into a ReadCloser.
    // Close ensures that the body has been fully read
    // and then reads the trailer if necessary.
    type body struct {
    	src          io.Reader
    	hdr          interface{}   // non-nil (Response or Request) value means read trailer
    	r            *bufio.Reader // underlying wire-format reader for the trailer
    	closing      bool          // is the connection to be closed after reading body?
    	doEarlyClose bool          // whether Close should stop early
    
    	mu         sync.Mutex // guards following, and calls to Read and Close
    	sawEOF     bool
    	closed     bool
    	earlyClose bool   // Close called and we didn't read to the end of src
    	onHitEOF   func() // if non-nil, func to call when EOF is Read
    }
    

    그래서 최종 close 방법 은 이 논 리 를 수행 합 니 다.
    func (b *body) Close() error {
    	b.mu.Lock()
    	defer b.mu.Unlock()
    	if b.closed {
    		return nil
    	}
    	var err error
    	switch {
    	case b.sawEOF:
    		// Already saw EOF, so no need going to look for it.
    	case b.hdr == nil && b.closing:
    		// no trailer and closing the connection next.
    		// no point in reading to EOF.
    	case b.doEarlyClose:
    		// Read up to maxPostHandlerReadBytes bytes of the body, looking
    		// for EOF (and trailers), so we can re-use this connection.
    		if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > maxPostHandlerReadBytes {
    			// There was a declared Content-Length, and we have more bytes remaining
    			// than our maxPostHandlerReadBytes tolerance. So, give up.
    			b.earlyClose = true
    		} else {
    			var n int64
    			// Consume the body, or, which will also lead to us reading
    			// the trailer headers after the body, if present.
    			n, err = io.CopyN(ioutil.Discard, bodyLocked{b}, maxPostHandlerReadBytes)
    			if err == io.EOF {
    				err = nil
    			}
    			if n == maxPostHandlerReadBytes {
    				b.earlyClose = true
    			}
    		}
    	default:
    		// Fully consume the body, which will also lead to us reading
    		// the trailer headers after the body, if present.
    		_, err = io.Copy(ioutil.Discard, bodyLocked{b})
    	}
    	b.closed = true
    	return err
    }
    

    위의 코드 주석 에서 말 한 바 와 같이 Close ensures that the body has been fully read 바디 가 깨끗하게 읽 을 수 있 도록 하 는 데 쓰 인 다.
    2. 왜 그 랬 어 요?
    간단 하 다:

    좋은 웹페이지 즐겨찾기