func ListItemValues(list interface{}, key interface{}, subKey ...interface{}) (values []interface{}) {
	var reflectValue reflect.Value
	if v, ok := list.(reflect.Value); ok {
		reflectValue = v
	} else {
		reflectValue = reflect.ValueOf(list)
	}
	reflectKind := reflectValue.Kind()
	for reflectKind == reflect.Ptr {
		reflectValue = reflectValue.Elem()
		reflectKind = reflectValue.Kind()
	}
	switch reflectKind {
	case reflect.Slice, reflect.Array:
		if reflectValue.Len() == 0 {
			return
		}
		values = []interface{}{}
		for i := 0; i < reflectValue.Len(); i++ {
			if value, ok := ItemValue(reflectValue.Index(i), key); ok {
				if len(subKey) > 0 && subKey[0] != nil {
					if subValue, ok := ItemValue(value, subKey[0]); ok {
						value = subValue
					} else {
						continue
					}
				}
				if array, ok := value.([]interface{}); ok {
					values = append(values, array...)
				} else {
					values = append(values, value)
				}
			}
		}
	}
	return
}
ListItemValues retrieves and returns the elements of all item struct/map with key `key`.
Note that the parameter `list` should be type of slice which contains elements of map or struct,
or else it returns an empty slice.

The parameter `list` supports types like:
[]map[string]interface{}
[]map[string]sub-map
[]struct
[]struct:sub-struct
Note that the sub-map/sub-struct makes sense only if the optional parameter `subKey` is given.
package gutil
import (
	"reflect"
)