github.com/songzhibin97/gkit@v1.2.13/tools/stm/stm.go (about) 1 package stm 2 3 import ( 4 "reflect" 5 "unsafe" 6 ) 7 8 // struct => map 9 10 func StructToMap(val interface{}, tag string) map[string]interface{} { 11 return structToMap(val, tag, false) 12 } 13 14 func StructToMapExtraExport(val interface{}, tag string) map[string]interface{} { 15 return structToMap(val, tag, true) 16 } 17 18 func structToMap(val interface{}, tag string, extraExport bool) map[string]interface{} { 19 t, v := reflect.TypeOf(val), reflect.ValueOf(val) 20 if v.Kind() == reflect.Ptr { 21 return structToMap(v.Elem().Interface(), tag, extraExport) 22 } 23 if v.Kind() != reflect.Struct { 24 return nil 25 } 26 mp := make(map[string]interface{}) 27 28 for i := 0; i < v.NumField(); i++ { 29 vField := v.Field(i) 30 name := t.Field(i).Name 31 if tag != "" { 32 ts := t.Field(i).Tag.Get(tag) 33 if ts == "-" { 34 continue 35 } 36 if ts != "" { 37 name = ts 38 } 39 } 40 if !vField.IsValid() { 41 continue 42 } 43 st := (vField.Kind() == reflect.Struct) || (vField.Kind() == reflect.Ptr && vField.Elem().Kind() == reflect.Struct) 44 if vField.CanInterface() { 45 iv := vField.Interface() 46 if st { 47 iv = structToMap(iv, tag, extraExport) 48 } 49 mp[name] = iv 50 } else if extraExport { 51 // 未导出 52 cp := reflect.New(v.Type()).Elem() 53 cp.Set(v) 54 value := cp.Field(i) 55 iv := reflect.NewAt(value.Type(), unsafe.Pointer(value.UnsafeAddr())).Elem().Interface() 56 if st { 57 iv = structToMap(iv, tag, extraExport) 58 } 59 mp[name] = iv 60 } 61 } 62 return mp 63 }