关闭可能是os.Stdin的io.Reader。

huangapple go评论89阅读模式
英文:

Closing an io.Reader that might be an os.Stdin

问题

我正在尝试根据给定的文件名设置文件输入,如果没有给定文件名,则使用标准输入。我原以为可以这样做:

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)
  }
}

传递给input的函数期望符合io.Reader接口的内容,并且一切都正常工作。以上代码是有效的...

直到我尝试找出一种关闭input的方法。尽管os.Stdin和os.Open返回的两种方式都可以关闭(当然,关闭stdin可能并不真正有意义,但也是无害的)。但编译器不知道创建input的两种方式都给我提供了实现Close()方法的内容。所以我想知道是否有一种方法可以告诉编译器Close()方法已经实现了input

英文:

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.

答案1

得分: 4

使用 io.ReadCloser 来声明 input 具有 Read 和 Close 方法:

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)
  }
}

如果在函数返回之前关闭文件,另一种选择是使用 defer 关闭文件:

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

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)
  }
}

If the file is closed just before return from the function, then another option is to defer the file close:

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

答案2

得分: 0

在撰写问题并努力解释清楚的过程中,我意识到使用以下方式声明输入可以解决问题:

var input *os.File

我在开始撰写问题之前没有注意到os.Stdin的类型。因此,我根据将使用该输入的函数所需的最通用接口声明了input

英文:

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.

答案3

得分: -1

要检查io.Reader是否实现了Close方法,可以使用类型断言,代码如下:

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

这段代码会将reader转换为io.Closer类型,并检查转换是否成功。如果成功,就可以调用Close方法关闭reader

英文:

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()
}

huangapple
  • 本文由 发表于 2021年9月27日 10:38:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/69340613.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定