github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/f/mapper.go (about) 1 package f 2 3 import ( 4 "reflect" 5 "sort" 6 "strings" 7 ) 8 9 // MapKeys get all keys of the given map. 10 func MapKeys(mp interface{}, sorted ...bool) (keys []string) { 11 rftVal := reflect.ValueOf(mp) 12 if rftVal.Type().Kind() == reflect.Ptr { 13 rftVal = rftVal.Elem() 14 } 15 16 if rftVal.Kind() != reflect.Map { 17 return 18 } 19 20 for _, key := range rftVal.MapKeys() { 21 keys = append(keys, key.String()) 22 } 23 24 if len(sorted) > 0 && sorted[0] { 25 sort.Strings(keys) 26 } 27 return 28 } 29 30 // MapKeysContains map keys contains key. 31 func MapKeysContains(mp map[string]interface{}, key string) bool { 32 for k := range mp { 33 if k == key { 34 return true 35 } 36 } 37 return false 38 } 39 40 // MapKeySorted Enable map keys to be retrieved in same order when iterating. 41 func MapKeySorted(mp map[string]interface{}) (keys []string) { 42 for key := range mp { 43 keys = append(keys, key) 44 } 45 sort.Strings(keys) 46 return keys 47 } 48 49 // MapValues get all values from the given map. 50 func MapValues(mp interface{}) (values []interface{}) { 51 rftTyp := reflect.TypeOf(mp) 52 if rftTyp.Kind() == reflect.Ptr { 53 rftTyp = rftTyp.Elem() 54 } 55 56 if rftTyp.Kind() != reflect.Map { 57 return 58 } 59 60 rftVal := reflect.ValueOf(mp) 61 for _, key := range rftVal.MapKeys() { 62 values = append(values, rftVal.MapIndex(key).Interface()) 63 } 64 return 65 } 66 67 // MapValuesContains map values contains value. 68 func MapValuesContains(mp map[string]interface{}, val interface{}) bool { 69 for _, v := range mp { 70 if reflect.DeepEqual(v, val) { 71 return true 72 } 73 } 74 return false 75 } 76 77 // MapValue get value from a map[string]interface{}. eg "top" "top.sub" 78 func MapValue(key string, mp map[string]interface{}) (val interface{}, ok bool) { 79 if val, ok := mp[key]; ok { 80 return val, true 81 } 82 83 // has sub key? eg. "top.sub" 84 if !strings.ContainsRune(key, '.') { 85 return nil, false 86 } 87 88 keys := strings.Split(key, ".") 89 topK := keys[0] 90 91 // find top item data based on top key 92 var item interface{} 93 if item, ok = mp[topK]; !ok { 94 return 95 } 96 97 for _, k := range keys[1:] { 98 switch tData := item.(type) { 99 case map[string]string: // is simple map 100 item, ok = tData[k] 101 if !ok { 102 return 103 } 104 case map[string]interface{}: // is map(decode from toml/json) 105 if item, ok = tData[k]; !ok { 106 return 107 } 108 case map[interface{}]interface{}: // is map(decode from yaml) 109 if item, ok = tData[k]; !ok { 110 return 111 } 112 default: // error 113 ok = false 114 return 115 } 116 } 117 118 return item, true 119 }