4

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

1

2 Answers 2

8

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.

Sign up to request clarification or add additional context in comments.

1 Comment

What's wrong with just doing _, ok := x.(io.Reader)? Then ok is true if x implements io.Reader and false otherwise.
5

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.