github.com/gogf/gf@v1.16.9/util/gconv/gconv_scan.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gconv
     8  
     9  import (
    10  	"github.com/gogf/gf/errors/gcode"
    11  	"github.com/gogf/gf/errors/gerror"
    12  	"reflect"
    13  )
    14  
    15  // Scan automatically checks the type of `pointer` and converts `params` to `pointer`. It supports `pointer`
    16  // with type of `*map/*[]map/*[]*map/*struct/**struct/*[]struct/*[]*struct` for converting.
    17  //
    18  // It calls function `doMapToMap`  internally if `pointer` is type of *map                 for converting.
    19  // It calls function `doMapToMaps` internally if `pointer` is type of *[]map/*[]*map       for converting.
    20  // It calls function `doStruct`    internally if `pointer` is type of *struct/**struct     for converting.
    21  // It calls function `doStructs`   internally if `pointer` is type of *[]struct/*[]*struct for converting.
    22  func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
    23  	var (
    24  		pointerType reflect.Type
    25  		pointerKind reflect.Kind
    26  	)
    27  	if v, ok := pointer.(reflect.Value); ok {
    28  		pointerType = v.Type()
    29  	} else {
    30  		pointerType = reflect.TypeOf(pointer)
    31  	}
    32  	if pointerType == nil {
    33  		return gerror.NewCode(gcode.CodeInvalidParameter, "parameter pointer should not be nil")
    34  	}
    35  	pointerKind = pointerType.Kind()
    36  	if pointerKind != reflect.Ptr {
    37  		return gerror.NewCodef(gcode.CodeInvalidParameter, "params should be type of pointer, but got type: %v", pointerKind)
    38  	}
    39  	var (
    40  		pointerElem               = pointerType.Elem()
    41  		pointerElemKind           = pointerElem.Kind()
    42  		keyToAttributeNameMapping map[string]string
    43  	)
    44  	if len(mapping) > 0 {
    45  		keyToAttributeNameMapping = mapping[0]
    46  	}
    47  	switch pointerElemKind {
    48  	case reflect.Map:
    49  		return doMapToMap(params, pointer, mapping...)
    50  
    51  	case reflect.Array, reflect.Slice:
    52  		var (
    53  			sliceElem     = pointerElem.Elem()
    54  			sliceElemKind = sliceElem.Kind()
    55  		)
    56  		for sliceElemKind == reflect.Ptr {
    57  			sliceElem = sliceElem.Elem()
    58  			sliceElemKind = sliceElem.Kind()
    59  		}
    60  		if sliceElemKind == reflect.Map {
    61  			return doMapToMaps(params, pointer, mapping...)
    62  		}
    63  		return doStructs(params, pointer, keyToAttributeNameMapping, "")
    64  
    65  	default:
    66  
    67  		return doStruct(params, pointer, keyToAttributeNameMapping, "")
    68  	}
    69  }
    70  
    71  // ScanDeep automatically calls StructDeep or StructsDeep function according to the type of
    72  // parameter `pointer` to implement the converting.
    73  //
    74  // It calls function StructDeep if `pointer` is type of *struct/**struct to do the converting.
    75  // It calls function StructsDeep if `pointer` is type of *[]struct/*[]*struct to do the converting.
    76  // Deprecated, use Scan instead.
    77  func ScanDeep(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
    78  	t := reflect.TypeOf(pointer)
    79  	k := t.Kind()
    80  	if k != reflect.Ptr {
    81  		return gerror.NewCodef(gcode.CodeInvalidParameter, "params should be type of pointer, but got: %v", k)
    82  	}
    83  	switch t.Elem().Kind() {
    84  	case reflect.Array, reflect.Slice:
    85  		return StructsDeep(params, pointer, mapping...)
    86  	default:
    87  		return StructDeep(params, pointer, mapping...)
    88  	}
    89  }