...

Source file src/github.com/thoas/go-funk/helpers.go

Documentation: github.com/thoas/go-funk

     1  package funk
     2  
     3  import (
     4  	"bytes"
     5  	"math/rand"
     6  	"reflect"
     7  )
     8  
     9  var numericZeros = []interface{}{
    10  	int(0),
    11  	int8(0),
    12  	int16(0),
    13  	int32(0),
    14  	int64(0),
    15  	uint(0),
    16  	uint8(0),
    17  	uint16(0),
    18  	uint32(0),
    19  	uint64(0),
    20  	float32(0),
    21  	float64(0),
    22  }
    23  
    24  // ToFloat64 converts any numeric value to float64.
    25  func ToFloat64(x interface{}) (float64, bool) {
    26  	var xf float64
    27  	xok := true
    28  
    29  	switch xn := x.(type) {
    30  	case uint8:
    31  		xf = float64(xn)
    32  	case uint16:
    33  		xf = float64(xn)
    34  	case uint32:
    35  		xf = float64(xn)
    36  	case uint64:
    37  		xf = float64(xn)
    38  	case int:
    39  		xf = float64(xn)
    40  	case int8:
    41  		xf = float64(xn)
    42  	case int16:
    43  		xf = float64(xn)
    44  	case int32:
    45  		xf = float64(xn)
    46  	case int64:
    47  		xf = float64(xn)
    48  	case float32:
    49  		xf = float64(xn)
    50  	case float64:
    51  		xf = float64(xn)
    52  	default:
    53  		xok = false
    54  	}
    55  
    56  	return xf, xok
    57  }
    58  
    59  // PtrOf makes a copy of the given interface and returns a pointer.
    60  func PtrOf(itf interface{}) interface{} {
    61  	t := reflect.TypeOf(itf)
    62  
    63  	cp := reflect.New(t)
    64  	cp.Elem().Set(reflect.ValueOf(itf))
    65  
    66  	// Avoid double pointers if itf is a pointer
    67  	if t.Kind() == reflect.Ptr {
    68  		return cp.Elem().Interface()
    69  	}
    70  
    71  	return cp.Interface()
    72  }
    73  
    74  // IsFunction returns if the argument is a function.
    75  func IsFunction(in interface{}, num ...int) bool {
    76  	funcType := reflect.TypeOf(in)
    77  
    78  	result := funcType != nil && funcType.Kind() == reflect.Func
    79  
    80  	if len(num) >= 1 {
    81  		result = result && funcType.NumIn() == num[0]
    82  	}
    83  
    84  	if len(num) == 2 {
    85  		result = result && funcType.NumOut() == num[1]
    86  	}
    87  
    88  	return result
    89  }
    90  
    91  // IsPredicate returns if the argument is a predicate function.
    92  func IsPredicate(in interface{}, inTypes ...reflect.Type) bool {
    93  	if len(inTypes) == 0 {
    94  		inTypes = append(inTypes, nil)
    95  	}
    96  
    97  	funcType := reflect.TypeOf(in)
    98  
    99  	result := funcType != nil && funcType.Kind() == reflect.Func
   100  
   101  	result = result && funcType.NumOut() == 1 && funcType.Out(0).Kind() == reflect.Bool
   102  	result = result && funcType.NumIn() == len(inTypes)
   103  
   104  	for i := 0; result && i < len(inTypes); i++ {
   105  		inType := inTypes[i]
   106  		result = inType == nil || inType.ConvertibleTo(funcType.In(i))
   107  	}
   108  
   109  	return result
   110  }
   111  
   112  // IsEqual returns if the two objects are equal
   113  func IsEqual(expected interface{}, actual interface{}) bool {
   114  	if expected == nil || actual == nil {
   115  		return expected == actual
   116  	}
   117  
   118  	if exp, ok := expected.([]byte); ok {
   119  		act, ok := actual.([]byte)
   120  		if !ok {
   121  			return false
   122  		}
   123  
   124  		if exp == nil || act == nil {
   125  			return true
   126  		}
   127  
   128  		return bytes.Equal(exp, act)
   129  	}
   130  
   131  	return reflect.DeepEqual(expected, actual)
   132  
   133  }
   134  
   135  // IsType returns if the two objects are in the same type
   136  func IsType(expected interface{}, actual interface{}) bool {
   137  	return IsEqual(reflect.TypeOf(expected), reflect.TypeOf(actual))
   138  }
   139  
   140  // Equal returns if the two objects are equal
   141  func Equal(expected interface{}, actual interface{}) bool {
   142  	return IsEqual(expected, actual)
   143  }
   144  
   145  // NotEqual returns if the two objects are not equal
   146  func NotEqual(expected interface{}, actual interface{}) bool {
   147  	return !IsEqual(expected, actual)
   148  }
   149  
   150  // IsIteratee returns if the argument is an iteratee.
   151  func IsIteratee(in interface{}) bool {
   152  	if in == nil {
   153  		return false
   154  	}
   155  	arrType := reflect.TypeOf(in)
   156  
   157  	kind := arrType.Kind()
   158  
   159  	return kind == reflect.Array || kind == reflect.Slice || kind == reflect.Map
   160  }
   161  
   162  // IsCollection returns if the argument is a collection.
   163  func IsCollection(in interface{}) bool {
   164  	arrType := reflect.TypeOf(in)
   165  
   166  	kind := arrType.Kind()
   167  
   168  	return kind == reflect.Array || kind == reflect.Slice
   169  }
   170  
   171  // SliceOf returns a slice which contains the element.
   172  func SliceOf(in interface{}) interface{} {
   173  	value := reflect.ValueOf(in)
   174  
   175  	sliceType := reflect.SliceOf(reflect.TypeOf(in))
   176  	slice := reflect.New(sliceType)
   177  	sliceValue := reflect.MakeSlice(sliceType, 0, 0)
   178  	sliceValue = reflect.Append(sliceValue, value)
   179  	slice.Elem().Set(sliceValue)
   180  
   181  	return slice.Elem().Interface()
   182  }
   183  
   184  // Any returns true if any element of the iterable is not empty. If the iterable is empty, return False.
   185  func Any(objs ...interface{}) bool {
   186  	if len(objs) == 0 {
   187  		return false
   188  	}
   189  
   190  	for _, obj := range objs {
   191  		if !IsEmpty(obj) {
   192  			return true
   193  		}
   194  	}
   195  
   196  	return false
   197  }
   198  
   199  // All returns true if all elements of the iterable are not empty (or if the iterable is empty)
   200  func All(objs ...interface{}) bool {
   201  	if len(objs) == 0 {
   202  		return true
   203  	}
   204  
   205  	for _, obj := range objs {
   206  		if IsEmpty(obj) {
   207  			return false
   208  		}
   209  	}
   210  
   211  	return true
   212  }
   213  
   214  // IsEmpty returns if the object is considered as empty or not.
   215  func IsEmpty(obj interface{}) bool {
   216  	if obj == nil || obj == "" || obj == false {
   217  		return true
   218  	}
   219  
   220  	for _, v := range numericZeros {
   221  		if obj == v {
   222  			return true
   223  		}
   224  	}
   225  
   226  	objValue := reflect.ValueOf(obj)
   227  
   228  	switch objValue.Kind() {
   229  	case reflect.Map:
   230  		fallthrough
   231  	case reflect.Slice, reflect.Chan:
   232  		return objValue.Len() == 0
   233  	case reflect.Struct:
   234  		return reflect.DeepEqual(obj, ZeroOf(obj))
   235  	case reflect.Ptr:
   236  		if objValue.IsNil() {
   237  			return true
   238  		}
   239  
   240  		obj = redirectValue(objValue).Interface()
   241  
   242  		return reflect.DeepEqual(obj, ZeroOf(obj))
   243  	}
   244  
   245  	return false
   246  }
   247  
   248  // IsZero returns if the object is considered as zero value
   249  func IsZero(obj interface{}) bool {
   250  	if obj == nil || obj == "" || obj == false {
   251  		return true
   252  	}
   253  
   254  	for _, v := range numericZeros {
   255  		if obj == v {
   256  			return true
   257  		}
   258  	}
   259  
   260  	return reflect.DeepEqual(obj, ZeroOf(obj))
   261  }
   262  
   263  // NotEmpty returns if the object is considered as non-empty or not.
   264  func NotEmpty(obj interface{}) bool {
   265  	return !IsEmpty(obj)
   266  }
   267  
   268  // ZeroOf returns a zero value of an element.
   269  func ZeroOf(in interface{}) interface{} {
   270  	if in == nil {
   271  		return nil
   272  	}
   273  
   274  	return reflect.Zero(reflect.TypeOf(in)).Interface()
   275  }
   276  
   277  // RandomInt generates a random int, based on a min and max values
   278  func RandomInt(min, max int) int {
   279  	return min + rand.Intn(max-min)
   280  }
   281  
   282  // Shard will shard a string name
   283  func Shard(str string, width int, depth int, restOnly bool) []string {
   284  	var results []string
   285  
   286  	for i := 0; i < depth; i++ {
   287  		results = append(results, str[(width*i):(width*(i+1))])
   288  	}
   289  
   290  	if restOnly {
   291  		results = append(results, str[(width*depth):])
   292  	} else {
   293  		results = append(results, str)
   294  	}
   295  
   296  	return results
   297  }
   298  
   299  var defaultLetters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
   300  
   301  // RandomString returns a random string with a fixed length
   302  func RandomString(n int, allowedChars ...[]rune) string {
   303  	var letters []rune
   304  
   305  	if len(allowedChars) == 0 {
   306  		letters = defaultLetters
   307  	} else {
   308  		letters = allowedChars[0]
   309  	}
   310  
   311  	b := make([]rune, n)
   312  	for i := range b {
   313  		b[i] = letters[rand.Intn(len(letters))]
   314  	}
   315  
   316  	return string(b)
   317  }
   318  

View as plain text