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  }