github.com/gogf/gf@v1.16.9/internal/structs/structs_type.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 structs 8 9 import ( 10 "errors" 11 "fmt" 12 "reflect" 13 ) 14 15 // StructType retrieves and returns the struct Type of specified struct/*struct. 16 // The parameter `object` should be either type of struct/*struct/[]struct/[]*struct. 17 func StructType(object interface{}) (*Type, error) { 18 var ( 19 reflectValue reflect.Value 20 reflectKind reflect.Kind 21 reflectType reflect.Type 22 ) 23 if rv, ok := object.(reflect.Value); ok { 24 reflectValue = rv 25 } else { 26 reflectValue = reflect.ValueOf(object) 27 } 28 reflectKind = reflectValue.Kind() 29 for { 30 switch reflectKind { 31 case reflect.Ptr: 32 if !reflectValue.IsValid() || reflectValue.IsNil() { 33 // If pointer is type of *struct and nil, then automatically create a temporary struct. 34 reflectValue = reflect.New(reflectValue.Type().Elem()).Elem() 35 reflectKind = reflectValue.Kind() 36 } else { 37 reflectValue = reflectValue.Elem() 38 reflectKind = reflectValue.Kind() 39 } 40 41 case reflect.Array, reflect.Slice: 42 reflectValue = reflect.New(reflectValue.Type().Elem()).Elem() 43 reflectKind = reflectValue.Kind() 44 45 default: 46 goto exitLoop 47 } 48 } 49 50 exitLoop: 51 for reflectKind == reflect.Ptr { 52 reflectValue = reflectValue.Elem() 53 reflectKind = reflectValue.Kind() 54 } 55 if reflectKind != reflect.Struct { 56 return nil, errors.New( 57 fmt.Sprintf( 58 `invalid object kind "%s", kind of "struct" is required`, 59 reflectKind, 60 ), 61 ) 62 } 63 reflectType = reflectValue.Type() 64 return &Type{ 65 Type: reflectType, 66 }, nil 67 } 68 69 // Signature returns a unique string as this type. 70 func (t Type) Signature() string { 71 return t.PkgPath() + "/" + t.String() 72 } 73 74 // FieldKeys returns the keys of current struct/map. 75 func (t Type) FieldKeys() []string { 76 keys := make([]string, t.NumField()) 77 for i := 0; i < t.NumField(); i++ { 78 keys[i] = t.Field(i).Name 79 } 80 return keys 81 }