Home > other >  Closing an io.Reader that might be an os.Stdin
Closing an io.Reader that might be an os.Stdin

Time:09-27

I am trying to set a file as input if a file name is given or use standard input if no file name is given. I would have thought that this is the way to do so:

var input io.Reader
if filename == "" {
  input = os.Stdin
} else {
  input, err = os.Open(filename)
  if err != nil {
    log.Fatalf("failed to open file: %v", err)
  }
}

The function that is passed input expects something that conforms to the io.Reader interface and all behaves well. That is the above works ...

It works until I try to figure out a way to close input. Although both things returned by os.Stdin and os.Open (sure, closing stdin might not really mean much, but it is harmless). The compiler doesn't know that both ways of creating input give me something that implements Close(). So I was wondering there there is a way to tell the compiler that Close() is implemented for input.

CodePudding user response:

Use io.ReadCloser to declare that input has Read and Close methods:

var input io.ReadCloser
if filename == "" {
  input = os.Stdin
} else {
  input, err = os.Open(filename)
  if err != nil {
    log.Fatalf("failed to open file: %v", err)
  }
}

CodePudding user response:

The way to check if an io.Reader implements Close is to use type assertion as:

if closer, ok:=reader.(io.Closer); ok {
   err:=closer.Close()
}

CodePudding user response:

Well in the course of writing up my question for others and working to spell things out, I realized that declaring input with

var input *os.File

fixes everything.

I have failed to look at the type of os.Stdin until I started to write up the question. And so I declared input in terms of the most general interface required by the function that will use it.

  •  Tags:  
  • go
  • Related