Custom func to transfer []whateverStruct to map[string]interface

I am trying to write a func with function to transfer []struct to map[string]interface.

type Another_struct struct {
	House   string
	Age     int
	HaveDog bool
	Name    string
}

func StructListToStructMap(structListInit interface{}, fieldNameAsMapKey string) map[string]interface{} {
	sortedData := make(map[string]interface{})
	structListValue := reflect.ValueOf(structListInit)

	for i := 0; i < structListValue.Len(); i++ {
		for j := 0; j < structListValue.Index(i).NumField(); j++ {
			fmt.Println(structListValue.Index(i).Field(j))
		}
		fmt.Println("=========================")

		keyStr := strconv.Itoa(i)
		sortedData[keyStr] = structListValue.Index(i)
	}

	/*structListType := reflect.TypeOf(structListInit)
	for i := 0; i < structListType.Len(); i++ {
		fmt.Println("-----------------")
	}
	fmt.Printf("%+v", structListType)*/

	return sortedData
}


func main() {
	var aaa []Another_struct
	//aaa := make([]Another_struct, 0, 10)
	for i := 0; i < 10; i++ {
		bbb := Another_struct{"a city name", 20 + i + 1, true, "james"}
		aaa = append(aaa, bbb)
	}
	//fmt.Println(aaa)
	//ccc := Struct2Map(aaa)
	ccc := StructListToStructMap(aaa, "Age")
	fmt.Println(ccc)
}

It should not be limited to []Another_struct, it should adopt whatever the struct is. as well the generated map[string]interface should have the certain feild value as key.

I have been thinking this for a very long time. and now come here for help.

I avoid reflection whenever possible. First, at least accept a []interface{} to avoid using reflection to access the slice, but it does have the downside that the caller would likely need to copy a []T to a []interface{}. Next, since the values of your returned map are to be the elements of the input slice, you don’t need to interrogate the elements except to generate the key. I’d also assume that somewhere there’s knowledge of the input struct and have the function accept another function that returns the key value from an element. Something like this:

func structListToStructMap(list []interface{}, getkey func(interface{})string) map[string]{}interface {
  out := make(map[string}interface{})
  for _, e := range list {
    key := getkey(e)
    out[key] = e
  }
  return out
}

You can do better using generics. Define your function with a type parameter T so that the arguments are l []T and getkey func(T)string and the return type is map[string]T. Most of the code would remain exactly the same. It would eliminate the copy necessitated by accepting a []interface{}.

If you must use reflection to retrieve the key from a struct, you can now isolate it to an implementation of the getkey function parameter.

thank you !

if the input parameter like list []interface{} in your code. I tried this at the first time in my mind. But I encountered problems on passing a var to it. the type not match.

Correct, that’s why I mentioned

An implementation with generics could avoid the copy.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.