How to check if a type satisfies an interface at runtime in Go

2 min read Tweet this post

In Go, interfaces are a powerful tool for creating flexible and extensible code. One of the benefits of interfaces is that they allow us to write code that works with any type that satisfies the interface, without having to know the concrete type of the object at compile time. However, sometimes we need to check at runtime whether a given type satisfies an interface or not. In this article, we’ll explore how to do that in Go.

Before we dive into checking whether a type satisfies an interface, let’s briefly review how to assert that a value implements an interface in Go. Go provides a special syntax for type assertions that allows us to check if a value is of a certain interface type, and if so, obtain its underlying value of that type. Here’s the basic syntax:

value, ok := object.(InterfaceType)

Here, object is the value we want to check, InterfaceType is the interface type we want to assert, value is a variable that will hold the underlying value of object if it implements InterfaceType, and ok is a boolean variable that will be set to true if the assertion succeeds, and false otherwise.

For example, suppose we have the following interface:

type Reader interface {
    Read(p []byte) (n int, err error)
}

We can use a type assertion to check if a value obj implements the Reader interface as follows:

if r, ok := obj.(Reader); ok {
    // obj implements the Reader interface, and r is the underlying value of type Reader
    // do something with r...
} else {
    // obj does not implement the Reader interface
}

Now that we know how to assert that a value implements an interface, let’s see how to check if a type satisfies an interface at runtime. In Go, we can check if a type T satisfies an interface I by checking if T implements all the methods of I. To do this, we can use the reflect package, which provides a set of functions and types for working with Go’s reflection API.

The reflect.Type interface represents a Go type, and provides a method called Implements that allows us to check if a type implements another type or interface. Here’s the basic syntax:

type T struct {...}

type I interface {...}

t := reflect.TypeOf(T{})
i := reflect.TypeOf((*I)(nil)).Elem()

if t.Implements(i) {
    // T implements the interface I
} else {
    // T does not implement the interface I
}

Here, we define a type T and an interface I. We then create a reflect.Type value t that represents the type T, and an interface{} value i that represents the interface I. We use the Elem method of reflect.Type to obtain the type of the interface value (which is I in this case).

We can then call the Implements method of t to check if T implements I. If it does, the method returns true, and if not, it returns false.

In this article, we’ve seen how to check if a type satisfies an interface at runtime in Go. By using type assertion and the reflect package, we can check if a type implements an interface by checking if it implements all the methods of the interface. This allows us to write flexible and extensible code that works with any type that satisfies an interface. From the two approach above I prefer to use assertion type instead of using reflection.

go interface practical