thoas / go-funk

A modern Go utility library which provides helpers (map, find, contains, filter, ...)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

funk.Get can't handle struct fields with interface{} type

radaiming opened this issue · comments

commented

Hello,

When trying following codes:

package main

import (
	"github.com/davecgh/go-spew/spew"
	"github.com/thoas/go-funk"
)

type Foo struct {
	Sth interface{}
}

type User struct {
	Phone struct {
		CountryCode string
		Number      int
	}
	Age int
}

func main() {
	e := Foo{
		Sth: User{
			Phone: struct {
				CountryCode string
				Number      int
			}{CountryCode: "+1", Number: 123},
			Age: 10,
		},
	}
	spew.Dump(funk.Get(e, "Sth.Age"))
	spew.Dump(funk.Get(e, "Sth.Phone.Number"))
	spew.Dump(funk.Get(e, "Sth.Phone.CountryCode"))
}

What I expect to get is:

(int) 10
(int) 123
(string) (len=2) "+1"

But actually I get 3 repeated

(main.User) {
Phone: (struct { CountryCode string; Number int }) {
CountryCode: (string) (len=2) "+1",
Number: (int) 123
},
Age: (int) 10
}

The reason looks like, Foo.Sth is interface type and redirectValue doesn't handle this, I try to fix it with this change:

-       if !value.IsValid() || value.Kind() != reflect.Ptr {
+       if !value.IsValid() || (value.Kind() != reflect.Ptr && value.Kind() != reflect.Interface) {
            return value
        }
 
-       res := reflect.Indirect(value)
+       res := value.Elem()

It works and all tests pass, but not sure if other things will be broken. If the change do work correctly, could you please apply it(or me send a PR)? Thanks.

commented

hi @radaiming,

You can send directly a PR for this and it will be tested by the CI.

commented

@thoas Is this issue taken by someone? if not, I would like to fix this