Ce face io.Closer
io.Closer are o singură metodă, Close() error. O implementează fișierele, conexiunile de rețea, corpul unui răspuns HTTP (resp.Body) și compresoarele (gzip.Writer).
Apare mai ales în combinații: io.ReadCloser (Reader + Closer), io.WriteCloser, io.ReadWriteCloser. Dacă primești un io.ReadCloser, ești responsabil să-l închizi. io.NopCloser(r) transformă un Reader obișnuit într-un ReadCloser al cărui Close nu face nimic.
Ce returnează
Close returnează nil sau eroarea de la închidere.
Exemple
Exemplul 1: Închiderea mai multor resurse
package main
import (
"fmt"
"io"
"os"
)
func inchideToate(resurse ...io.Closer) {
for _, r := range resurse {
if err := r.Close(); err != nil {
fmt.Println("eroare la închidere:", err)
}
}
}
func main() {
a, _ := os.Create("a.txt")
b, _ := os.Create("b.txt")
inchideToate(a, b)
inchideToate(a) // a doua oară: eroare
}
Rezultat
eroare la închidere: close a.txt: file already closed
Exemplul 2: Un tip propriu care se închide
package main
import (
"fmt"
"io"
)
type conexiune struct {
nume string
}
func (c *conexiune) Close() error {
fmt.Println("închid conexiunea", c.nume)
return nil
}
func foloseste(c io.Closer) {
defer c.Close()
fmt.Println("lucrez...")
}
func main() {
foloseste(&conexiune{nume: "baza-de-date"})
}
Rezultat
lucrez...
închid conexiunea baza-de-date
Exemplul 3: io.NopCloser
O funcție cere io.ReadCloser, dar noi avem doar un text. NopCloser adaugă un Close care nu face nimic.
package main
import (
"fmt"
"io"
"strings"
)
func citesteCorp(corp io.ReadCloser) string {
defer corp.Close()
date, _ := io.ReadAll(corp)
return string(date)
}
func main() {
corp := io.NopCloser(strings.NewReader(`{"status":"ok"}`))
fmt.Println(citesteCorp(corp))
}
Rezultat
{"status":"ok"}
Greșeli frecvente
- Uiți
resp.Body.Close()după o cerere HTTP. Conexiunea nu poate fi refolosită și resursele se adună.
Comenzi înrudite
os.File.Close: Închide fișierul și eliberează resursele sistemului; după Close fișierul nu mai poate fi folosit.io.Reader: Interfața pentru orice sursă de date din care se poate citi: fișiere, text, conexiuni, răspunsuri HTTP.io.Writer: Interfața pentru orice destinație în care se pot scrie octeți: fișiere, ecran, buffer-e, răspunsuri HTTP.io.ReadWriter: Interfața pentru tipurile din care se poate și citi, și în care se poate scrie (Reader + Writer).io.NopCloser: Transformă un Reader obișnuit într-un io.ReadCloser al cărui Close nu face nimic.