I want to know whether a concrete type implements a specefic interface and print it out. I have written an example [0] with a self defined struct (MyPoint) beeing not an interface-type. MyPoint has the function Read as defined in the interface of io.Reader:
type MyPoint struct {
X, Y int
}
func (pnt *MyPoint) Read(p []byte) (n int, err error) {
return 42, nil
}
The aim is to get the information that the concrete type p implements the interface io.Writer. Therefore I have written a short main trieng to get a true for the check.
func main() {
p := MyPoint{1, 2}
}
The first idea was to check it with the help of reflection and a type-switch and adding check(p)
to to the main-function.
func checkType(tst interface{}) {
switch tst.(type) {
case nil:
fmt.Printf("nil")
case *io.Reader:
fmt.Printf("p is of type io.Reader\n")
case MyPoint:
fmt.Printf("p is of type MyPoint\n")
default:
fmt.Println("p is unknown.")
}
}
The output is: p is of type MyPoint
. After a bit of research I know that I should have expected that because Go's types are static and therefore the type of p is MyPoint and not io.Reader. In addition to that io.Reader is an interface-type which is different to type MyPoint.
I found one solution e.g. at [1] which checks whether MyPoint can be an io.Reader at compile time. It works.
var _ io.Reader = (*MyPoint)(nil)
But that isn't the solution I wanted. Tries like below fails, too. I think it's because of the reason above, isn't it?
i := interface{}(new(MyPoint))
if _, ok := i.(io.Reader); ok {
fmt.Println("i is an io.Reader")
}
pType := reflect.TypeOf(p)
if _, ok := pType.(io.Reader); ok {
fmt.Println("The type of p is compatible to io.Reader")
}
readerType := reflect.TypeOf((*io.Reader)(nil)).Elem()
fmt.Printf("p impl. Reader %t \n", pType.Implements(readerType))
Exists one solution to check whether p implements the interface without compiling? I hope that someone can help me.
[0] http://play.golang.org/p/JCsFf7y74C (fixed) http://play.golang.org/p/cIStOOI84Y (old)
[1] Explanation of checking if value implements interface. Golang
It is perfectly possible to do what you want with the reflect package. Here is an example:
package main
import (
"fmt"
"io"
"reflect"
)
type Other int
type MyPoint struct {
X, Y int
}
func (pnt *MyPoint) Read(p []byte) (n int, err error) {
return 42, nil
}
func check(x interface{}) bool {
// Declare a type object representing io.Reader
reader := reflect.TypeOf((*io.Reader)(nil)).Elem()
// Get a type object of the pointer on the object represented by the parameter
// and see if it implements io.Reader
return reflect.PtrTo(reflect.TypeOf(x)).Implements(reader)
}
func main() {
x := MyPoint{0, 0}
y := Other(1)
fmt.Println(check(x)) // true
fmt.Println(check(y)) // false
}
The tricky point is to pay attention to how pointers are handled.
Exists one solution to check whether p implements the interface without compiling?
Yes: Careful reading of the code :-)
How could that be possible? p implements some interface i if the method set of p covers i. You will always have to compile the code.
I assume you want to fail not during compilation but just print during runtime.
The trick is getting a non-nil interface type which can be tested with the Implements
method of reflect.Type
:
pt := reflect.TypeOf(&MyPoint{})
ioReaderType := reflect.TypeOf((*io.Reader)(nil)).Elem()
fmt.Println(pt.Implements(ioReaderType)) // ==> true
http://play.golang.org/p/2Qcpfjm4ft
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With