46 lines
1.2 KiB
Go
46 lines
1.2 KiB
Go
package util
|
|
|
|
import (
|
|
"reflect"
|
|
)
|
|
|
|
// Implements get reflect.Zero(T) and (o).Implements(T)
|
|
func Implements[T any](o any) (T, bool) {
|
|
iface := reflect.TypeOf((*T)(nil)).Elem()
|
|
|
|
reflectType := reflect.TypeOf(o)
|
|
|
|
if alreadyReflectType, ok := o.(reflect.Type); ok {
|
|
reflectType = alreadyReflectType
|
|
o = reflect.Zero(reflectType).Interface()
|
|
} else if alreadyReflectValue, ok := o.(reflect.Value); ok {
|
|
reflectType = alreadyReflectValue.Type()
|
|
o = alreadyReflectValue.Interface()
|
|
}
|
|
|
|
if reflectType.Implements(iface) {
|
|
if reflectType.Kind() == reflect.Interface {
|
|
return *reflect.New(iface).Interface().(*T), true
|
|
}
|
|
return o.(T), true
|
|
} else {
|
|
return *reflect.New(iface).Interface().(*T), false
|
|
}
|
|
}
|
|
|
|
// PointerImplements get reflect.New(T) and (&o).Implements(T)
|
|
func PointerImplements[I any](o any) (reflect.Value, bool) {
|
|
iface := reflect.TypeOf((*I)(nil)).Elem()
|
|
|
|
reflectType := reflect.TypeOf(&o)
|
|
if alreadyReflectType, ok := o.(reflect.Type); ok {
|
|
reflectType = reflect.PointerTo(alreadyReflectType)
|
|
} else if alreadyReflectValue, ok := o.(reflect.Value); ok {
|
|
reflectType = reflect.PointerTo(alreadyReflectValue.Type())
|
|
}
|
|
|
|
reflectValue := reflect.New(reflectType.Elem())
|
|
|
|
return reflectValue, reflectType.Implements(iface)
|
|
}
|