Golang http Client.Do() 문서에 보면 아래와 같은 내용이 명시
If the returned error is nil, the Response will contain a non-nil Body which the user is expected to close. If the Body is not both read to EOF and closed, the Client's underlying RoundTripper (typically Transport) may not be able to re-use a persistent TCP connection to the server for a subsequent "keep-alive" request.
ioutil.ReadAll()
), 닫아야한다(response.Body.Close()
)resp, err := http.Get("<https://api.ipify.org?format=json>")
if resp != nil {
// 일반적인 경우에는 err가 nil이 아니면 resp가 nil이지만
// redirection 실패의 경우에는 resp가 nil이 아닐수도 있다고 함
defer resp.Body.Close()
}
if err != nil {
fmt.Println(err)
return
}
body, err := ioutil.ReadAll(resp.Body)
// _, err = io.Copy(ioutil.Discard, resp.Body) 만약 body를 사용하지 않는다면
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
for문 안에서 http request를 보내는 경우
for ... {
resp, err := http.Get("<https://api.ipify.org?format=json>")
if err != nil {
fmt.Println(err)
return
}
body, err := ioutil.ReadAll(resp.Body)
// body를 읽은 다음 바로 Close를 하여 커넥션 재사용이 가능하게
// defer를 한다면 for문이 종료되기 전까지 close가 되지 않아 재사용이 안될 가능성 존재
if resp != nil {
resp.Body.Close()
}
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
3가지 방식의 read가 존재
cursor.Next()
cursor.ReadAll()
cursor.TryNext()
(tailable cursor)기본적으로 Client가 데이터를 모두 소비하면 커서는 close 된다고 기술되어 있음. 하지만 cursor.Next() cursor.TryNext()
는 close가 되지 않아(individual, tailable), 명시적으로 cursor를 닫아주어야 함.
func (manager *Manager) decodeCursor(cursor *mongo.Cursor) ([]Document, error) {
if cursor != nil {
defer cursor.Close(context.TODO())
res := make([]Document, 0, 2)
for cursor.Next(context.TODO()) {
var document Document
err := cursor.Decode(&document)
if err == nil {
res = append(res, document)
} else {
return nil, err
}
}
return res, nil
}
return nil, errors.New("failed to find result")
}