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 }