5

Could someone please explain (or/and share examples) when and why readers should to be closed explicitly, i.e. implement io.ReadCloser, not just io.Reader.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Alexander
  • 149
  • 2
  • 8

2 Answers2

6

For example, when you are working with files, or any resource that should be closed to release the allocated resource (or memory for example for your resource, e.g. C code calling from Go).
You may use it when you have Read and Close methods, an example to show that you may use one common function to work with different types using io.ReadCloser:

package main

import (
    "fmt"
    "io"
    "log"
    "os"
)

func main() {
    f, err := os.Open("./main.go")
    if err != nil {
        log.Fatal(err)
    }
    doIt(f)
    doIt(os.Stdin)
}
func doIt(rc io.ReadCloser) {
    defer rc.Close()
    buf := make([]byte, 4)
    n, err := rc.Read(buf)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", buf[:n])
}

Run and enter 12345 as an input, Output:

pack
12345
1234

See also:
Does Go automatically close resources if not explicitly closed?

wasmup
  • 14,541
  • 6
  • 42
  • 58
4

It's for an explicit definition of Reader and Closer interface. So let's say you write some functionality that reads data, but you also want to close resource after doing it (again not to leak descriptors).

func ...(r io.ReaderCloser) {
    defer r.Close()
    ... // some reading
}

anything you pass in it will need to have both interfaces defined, is it os.File or any custom struct, in this case, you are forcing client of your API to define Read and Close interfaces implementations, not just io.Reader.

Oleg Butuzov
  • 4,795
  • 2
  • 24
  • 33