To be more concrete:
I have 2 Readers. One I get from os.Open("someExistingFile") and the other one from strings.NewReader("hello world").
One of them implemets Name(), the other one doesn't. I want to either make the other one also implement Name() (e.g. returning "") or (preferred) only call Name() if the type of the actual parameter supports it.
I hope the code fragment below indicates clearly what I want to solve.
I played around with different receivers, even with reflection but I didn't get to the point ...
package main
import (
"io"
"os"
"strings"
)
func main() {
stringReader := strings.NewReader("hello world")
fileReader, _ := os.Open("someExistingFile") // error handling omitted
fileReader.Name()
printFilenameIfReaderIsFile(stringReader)
printFilenameIfReaderIsFile(fileReader)
}
func printFilenameIfReaderIsFile(reader io.Reader) {
// here I want to ...
// ... either check if this reader is of type os.File and in this case call its Name() method (preferred)
// ... or use a custom type instead of io.Reader.
// This type's Name() method should return the filename for fileReader and nil for stringReader.
}
You're looking for the type switch control structure.
Your printFilenameIfReaderIsFile
function should look like (not actually checked):
func printFilenameIfReaderIsFile(reader io.Reader) {
switch f := reader.(type) {
case *os.File:
// f is now *os.File (not a os.File!)
fmt.Printf("%s
", f.Name())
}
}
EDIT: Don't forget, that os.Open
returns a *os.File
instead of an os.File
see docs!