How to Check If a Value Implements an Interface in Go

You cannot directly check if a specific value implements an interface at compile time, but you can verify it at runtime using a type assertion or by assigning the value to a variable of the interface type.

You cannot directly check if a specific value implements an interface at compile time, but you can verify it at runtime using a type assertion or by assigning the value to a variable of the interface type. If the assignment succeeds, the value implements the interface; if you need a boolean result without a panic, use the comma-ok idiom with a type assertion.

The most idiomatic way to check this is to attempt a type assertion into the interface type. If the value implements the interface, the assertion returns true and the interface value; otherwise, it returns false and the zero value of the interface. This approach is safe and avoids panics.

package main

import "fmt"

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

func main() {
    var data []byte
    
    // Check if data implements Reader
    if r, ok := interface{}(data).(Reader); ok {
        fmt.Println("data implements Reader")
        _ = r
    } else {
        fmt.Println("data does not implement Reader")
    }

    // Alternatively, check if a concrete type implements an interface
    type MyReader struct{}
    func (MyReader) Read(p []byte) (int, error) { return 0, nil }

    var m MyReader
    if _, ok := interface{}(m).(Reader); ok {
        fmt.Println("MyReader implements Reader")
    }
}

If you need to perform this check inside a generic function or a helper, you can wrap the logic to return a boolean. Note that you must cast the value to interface{} first before asserting to the specific interface type, as Go does not allow direct type assertions from concrete types to interfaces in all contexts without this intermediate step.

func implementsInterface(v any, iface interface{}) bool {
    // This is a generic check, but usually you check specific interfaces
    // The most common pattern is direct assertion as shown above.
    // For a generic check using reflection (less efficient):
    return false // Placeholder for reflection logic if needed
}

// Practical usage without reflection:
func isReader(v any) bool {
    _, ok := v.(Reader)
    return ok
}

Remember that interface satisfaction in Go is implicit. If a type has the required methods, it satisfies the interface automatically. You only need to check at runtime if you are dealing with dynamic values (like any or interface{}) where the concrete type is not known at compile time. For static types, the compiler will catch mismatches immediately, making runtime checks unnecessary.