gitee.com/go-spring2/spring-base@v1.1.3/util/type.go (about) 1 /* 2 * Copyright 2012-2019 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //go:generate mockgen -build_flags="-mod=mod" -package=util -source=type.go -destination=type_mock.go 18 19 package util 20 21 import ( 22 "context" 23 "reflect" 24 "strings" 25 ) 26 27 // errorType the reflection type of error. 28 var errorType = reflect.TypeOf((*error)(nil)).Elem() 29 30 // contextType the reflection type of context.Context. 31 var contextType = reflect.TypeOf((*context.Context)(nil)).Elem() 32 33 // TypeName returns a fully qualified name consisting of package path and type name. 34 func TypeName(i interface{}) string { 35 36 var typ reflect.Type 37 switch o := i.(type) { 38 case reflect.Type: 39 typ = o 40 case reflect.Value: 41 typ = o.Type() 42 default: 43 typ = reflect.TypeOf(o) 44 } 45 46 for { 47 if k := typ.Kind(); k == reflect.Ptr || k == reflect.Slice { 48 typ = typ.Elem() 49 } else { 50 break 51 } 52 } 53 54 if pkgPath := typ.PkgPath(); pkgPath != "" { 55 pkgPath = strings.TrimSuffix(pkgPath, "_test") 56 return pkgPath + "/" + typ.String() 57 } 58 return typ.String() // the path of built-in type is empty 59 } 60 61 // A BeanSelector can be the ID of a bean, a `reflect.Type`, a pointer such as 62 // `(*error)(nil)`, or a BeanDefinition value. 63 type BeanSelector interface{} 64 65 // A BeanDefinition describes a bean whose lifecycle is managed by IoC container. 66 type BeanDefinition interface { 67 Type() reflect.Type 68 Value() reflect.Value 69 Interface() interface{} 70 ID() string 71 BeanName() string 72 TypeName() string 73 Created() bool 74 Wired() bool 75 } 76 77 // Converter converts string value into user-defined value. It should be function 78 // type, and its prototype is func(string)(type,error). 79 type Converter interface{} 80 81 // IsConverter returns whether `t` is a converter type. 82 func IsConverter(t reflect.Type) bool { 83 return IsFuncType(t) && 84 t.NumIn() == 1 && 85 t.In(0).Kind() == reflect.String && 86 t.NumOut() == 2 && 87 (IsValueType(t.Out(0)) || IsFuncType(t.Out(0))) && IsErrorType(t.Out(1)) 88 } 89 90 // IsFuncType returns whether `t` is func type. 91 func IsFuncType(t reflect.Type) bool { 92 return t.Kind() == reflect.Func 93 } 94 95 // IsErrorType returns whether `t` is error type. 96 func IsErrorType(t reflect.Type) bool { 97 return t == errorType || t.Implements(errorType) 98 } 99 100 // IsContextType returns whether `t` is context.Context type. 101 func IsContextType(t reflect.Type) bool { 102 return t == contextType || t.Implements(contextType) 103 } 104 105 // ReturnNothing returns whether the function has no return value. 106 func ReturnNothing(t reflect.Type) bool { 107 return t.NumOut() == 0 108 } 109 110 // ReturnOnlyError returns whether the function returns only error value. 111 func ReturnOnlyError(t reflect.Type) bool { 112 return t.NumOut() == 1 && IsErrorType(t.Out(0)) 113 } 114 115 // IsStructPtr returns whether it is the pointer type of structure. 116 func IsStructPtr(t reflect.Type) bool { 117 return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct 118 } 119 120 // IsConstructor returns whether `t` is a constructor type. What is a constructor? 121 // It should be a function first, has any number of inputs and supports the option 122 // pattern input, has one or two outputs and the second output should be an error. 123 func IsConstructor(t reflect.Type) bool { 124 returnError := t.NumOut() == 2 && IsErrorType(t.Out(1)) 125 return IsFuncType(t) && (t.NumOut() == 1 || returnError) 126 } 127 128 // HasReceiver returns whether the function has a receiver. 129 func HasReceiver(t reflect.Type, receiver reflect.Value) bool { 130 if t.NumIn() < 1 { 131 return false 132 } 133 t0 := t.In(0) 134 if t0.Kind() != reflect.Interface { 135 return t0 == receiver.Type() 136 } 137 return receiver.Type().Implements(t0) 138 } 139 140 // IsPrimitiveValueType returns whether `t` is the primitive value type which only is 141 // int, unit, float, bool, string and complex. 142 func IsPrimitiveValueType(t reflect.Type) bool { 143 switch t.Kind() { 144 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 145 return true 146 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 147 return true 148 case reflect.Complex64, reflect.Complex128: 149 return true 150 case reflect.Float32, reflect.Float64: 151 return true 152 case reflect.String: 153 return true 154 case reflect.Bool: 155 return true 156 } 157 return false 158 } 159 160 // IsValueType returns whether the input type is the primitive value type and their 161 // composite type including array, slice, map and struct, such as []int, [3]string, 162 // []string, map[int]int, map[string]string, etc. 163 func IsValueType(t reflect.Type) bool { 164 fn := func(t reflect.Type) bool { 165 return IsPrimitiveValueType(t) || t.Kind() == reflect.Struct 166 } 167 switch t.Kind() { 168 case reflect.Map, reflect.Slice, reflect.Array: 169 return fn(t.Elem()) 170 default: 171 return fn(t) 172 } 173 } 174 175 // IsBeanType returns whether `t` is a bean type. 176 func IsBeanType(t reflect.Type) bool { 177 switch t.Kind() { 178 case reflect.Chan, reflect.Func, reflect.Interface: 179 return true 180 case reflect.Ptr: 181 return t.Elem().Kind() == reflect.Struct 182 default: 183 return false 184 } 185 } 186 187 // IsBeanReceiver returns whether the `t` is a bean receiver, a bean receiver can 188 // be a bean, a map or slice whose elements are beans. 189 func IsBeanReceiver(t reflect.Type) bool { 190 switch t.Kind() { 191 case reflect.Map, reflect.Slice, reflect.Array: 192 return IsBeanType(t.Elem()) 193 default: 194 return IsBeanType(t) 195 } 196 }