我希望func OpenFile()读取gzip文件和bzip2文件。稍后我将添加其他类型。
func OpenFile(name string) io.Reader{
file, err := os.Open(name)
if err != nil {
log.Fatal(err)
}
if(strings.Contains(name, ".gz")){
gzip, gerr := gzip.NewReader(file)
if gerr != nil {
log.Fatal(gerr)
}
return gzip
}else if(strings.Contains(name, ".bz2")){
bzip2 := bzip2.NewReader(file)
return bzip2
}else{
return file
}
}
我在另一个函数A中调用OpenFile():
in := OpenFile(p)
for _, d := range fdb.Detect(in) {
set[d] = true
counter++
}
...
我的问题是,如果我在OpenFile()中使用“defer file.Close()”,该文件将关闭得太早,因此我无法获得任何输入值。如何关闭A中的文件?
请注意,gzip.NewReader(file)和bzip2.NewReader(file)返回不同的接口(interface)。
gzip:func NewReader(r io.Reader)(* Reader,error)//阅读器具有func Close()
bzip2:func NewReader(r io.Reader)io.Reader//io.Reader没有func Close()
这就是我不能首先返回NewReader(file)的原因。
谢谢!
最佳答案
正如其他人提到的,您应该从函数中返回一个io.ReadCloser
。由于bzip2.NewReader()
的返回值不满足io.ReadCloser
,因此您需要创建自己的类型。
type myFileType struct {
io.Reader
io.Closer
}
func OpenFile(name string) io.ReadCloser {
file, err := os.Open(name)
if err != nil {
log.Fatal(err)
}
if strings.Contains(name, ".gz") {
gzip, gerr := gzip.NewReader(file)
if gerr != nil {
log.Fatal(gerr)
}
return gzip
} else if strings.Contains(name, ".bz2") {
bzip2 := bzip2.NewReader(file)
return myFileType{bzip2, file}
} else {
return file
}
}