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  }