I'm trying to determine if a field on a struct
implements a given interface that has a pointer receiver.
I have a go playground setup with my confusion .
Say I have the following interface
:
type Stringee interface {
FromString(s string) error
}
With an enum implementing it:
type Enum int
const (
EnumUnknown Enum = iota
EnumA
EnumB
)
func (my *Enum) String() string { return enumToStr[*my] }
func (my *Enum) FromString(s string) error {
if v, ok := enumFromStr[s]; ok {
*my = v
return nil
}
return errors.New("invalid value")
}
var enumToStr = map[Enum]string{
EnumA: "A",
EnumB: "B",
}
var enumFromStr = func() map[string]Enum {
m := make(map[string]Enum)
for k, v := range enumToStr {
m[v] = k
}
return m
}()
I first get the Type
of the interface
:
var stringeeType = reflect.TypeOf(new(Stringee)).Elem()
then I can perform checks against it:
e := EnumA
e.FromString("B")
e.String() // "B"
reflect.ValueOf(e).Type().Implements(stringeeType) // false
reflect.ValueOf(&e).Type().Implements(stringeeType) // true
Which is to be expected. However, what I don't know how to do is perform the check as a pointer if type is a field of a struct
. For example:
Say I have the following struct
:
type Struct struct {
E Enum
}
How do I check to see whether or not E
implements the interface
Stringee
?
t := Struct{}
tv := reflect.ValueOf(&t)
fieldE := tv.Elem().Field(0)
fieldE.Type().Implements(stringeeType) // false
If the field is addressable, then take the address of the field and check that value:
if fieldE.CannAddr() {
impl := fieldE.Addr().Type().Implements(stringeeType)
fmt.Println("&T.E implements Stringee", impl)
}
Alternatively if you have only the reflect.Type
not the relect.Value
, for example when checking if a struct's field implements an interface, you can use reflect.PtrTo
for this.
This func will check if any field of the given struct implements Stringee
:
func CheckFields(s interface{}) {
rt := reflect.TypeOf(s)
for i := 0; i < rt.NumField(); i++ {
field := rt.Field(i)
ptr := reflect.PtrTo(field.Type)
if ptr.Implements(stringeeType) {
fmt.Println(field.Name + " implements Stringee")
}
}
}
type Test struct {
Field int
Field2 MyTypeWithStringee
}
test := Test{}
CheckFields(test)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.