github.com/aldelo/common@v1.5.1/helper-other.go (about) 1 package helper 2 3 import ( 4 "fmt" 5 "reflect" 6 "runtime" 7 "strings" 8 "time" 9 ) 10 11 /* 12 * Copyright 2020-2023 Aldelo, LP 13 * 14 * Licensed under the Apache License, Version 2.0 (the "License"); 15 * you may not use this file except in compliance with the License. 16 * You may obtain a copy of the License at 17 * 18 * http://www.apache.org/licenses/LICENSE-2.0 19 * 20 * Unless required by applicable law or agreed to in writing, software 21 * distributed under the License is distributed on an "AS IS" BASIS, 22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 * See the License for the specific language governing permissions and 24 * limitations under the License. 25 */ 26 27 // ================================================================================================================ 28 // Variadic Optional Value Helpers 29 // ================================================================================================================ 30 31 // GetFirstOrDefault will select the first variadic value from paramValue, 32 // if no paramValue variadic, then defaultValue is used as return value 33 func GetFirstOrDefault(defaultValue interface{}, paramValue ...interface{}) interface{} { 34 if len(paramValue) > 0 { 35 return paramValue[0] 36 } else { 37 // returning default 38 return defaultValue 39 } 40 } 41 42 // GetFirstIntOrDefault will select the first variadic value from paramValue, 43 // if no paramValue variadic, then defaultValue is used as return value 44 func GetFirstIntOrDefault(defaultValue int, paramValue ...int) int { 45 if len(paramValue) > 0 { 46 return paramValue[0] 47 } else { 48 // returning default 49 return defaultValue 50 } 51 } 52 53 // GetFirstInt64OrDefault will select the first variadic value from paramValue, 54 // if no paramValue variadic, then defaultValue is used as return value 55 func GetFirstInt64OrDefault(defaultValue int64, paramValue ...int64) int64 { 56 if len(paramValue) > 0 { 57 return paramValue[0] 58 } else { 59 // returning default 60 return defaultValue 61 } 62 } 63 64 // GetFirstStringOrDefault will select the first variadic value from paramValue, 65 // if no paramValue variadic, then defaultValue is used as return value 66 func GetFirstStringOrDefault(defaultValue string, paramValue ...string) string { 67 if len(paramValue) > 0 { 68 return paramValue[0] 69 } else { 70 // returning default 71 return defaultValue 72 } 73 } 74 75 // GetFirstBoolOrDefault will select the first variadic value from paramValue, 76 // if no paramValue variadic, then defaultValue is used as return value 77 func GetFirstBoolOrDefault(defaultValue bool, paramValue ...bool) bool { 78 if len(paramValue) > 0 { 79 return paramValue[0] 80 } else { 81 // returning default 82 return defaultValue 83 } 84 } 85 86 // GetFirstFloat32OrDefault will select the first variadic value from paramValue, 87 // if no paramValue variadic, then defaultValue is used as return value 88 func GetFirstFloat32OrDefault(defaultValue float32, paramValue ...float32) float32 { 89 if len(paramValue) > 0 { 90 return paramValue[0] 91 } else { 92 // returning default 93 return defaultValue 94 } 95 } 96 97 // GetFirstFloat64OrDefault will select the first variadic value from paramValue, 98 // if no paramValue variadic, then defaultValue is used as return value 99 func GetFirstFloat64OrDefault(defaultValue float64, paramValue ...float64) float64 { 100 if len(paramValue) > 0 { 101 return paramValue[0] 102 } else { 103 // returning default 104 return defaultValue 105 } 106 } 107 108 // GetFirstTimeOrDefault will select the first variadic value from paramValue, 109 // if no paramValue variadic, then defaultValue is used as return value 110 func GetFirstTimeOrDefault(defaultValue time.Time, paramValue ...time.Time) time.Time { 111 if len(paramValue) > 0 { 112 return paramValue[0] 113 } else { 114 // returning default 115 return defaultValue 116 } 117 } 118 119 // GetFirstByteOrDefault will select the first variadic value from paramValue, 120 // if no paramValue variadic, then defaultValue is used as return value 121 func GetFirstByteOrDefault(defaultValue byte, paramValue ...byte) byte { 122 if len(paramValue) > 0 { 123 return paramValue[0] 124 } else { 125 // returning default 126 return defaultValue 127 } 128 } 129 130 // ================================================================================================================ 131 // slice helpers 132 // ================================================================================================================ 133 134 // IntSliceContains checks if value is contained within the intSlice 135 func IntSliceContains(intSlice *[]int, value int) bool { 136 if intSlice == nil { 137 return false 138 } else { 139 for _, v := range *intSlice { 140 if v == value { 141 return true 142 } 143 } 144 145 return false 146 } 147 } 148 149 // StringSliceContains checks if value is contained within the strSlice 150 func StringSliceContains(strSlice *[]string, value string) bool { 151 if strSlice == nil { 152 return false 153 } else { 154 for _, v := range *strSlice { 155 if strings.ToLower(v) == strings.ToLower(value) { 156 return true 157 } 158 } 159 160 return false 161 } 162 } 163 164 // StringSliceExtractUnique returns unique string slice elements 165 func StringSliceExtractUnique(strSlice []string) (result []string) { 166 if strSlice == nil { 167 return []string{} 168 } else if len(strSlice) <= 1 { 169 return strSlice 170 } else { 171 for _, v := range strSlice { 172 if !StringSliceContains(&result, v) { 173 result = append(result, v) 174 } 175 } 176 177 return result 178 } 179 } 180 181 // SliceSeekElement returns the first filterFunc input object's true response 182 // note: use SliceObjectToSliceInterface to convert slice of objects to slice of interface before passing to slice parameter 183 func SliceSeekElement(slice []interface{}, filterFunc func(input interface{}, filter ...interface{}) bool, filterParam ...interface{}) interface{} { 184 if len(slice) == 0 { 185 return nil 186 } 187 188 if filterFunc == nil { 189 return nil 190 } 191 192 if len(filterParam) == 0 { 193 return nil 194 } 195 196 for _, v := range slice { 197 if filterFunc(v, filterParam...) { 198 // found 199 return v 200 } 201 } 202 203 // not found 204 return nil 205 } 206 207 // SliceDeleteElement accepts slice (value type or pointer type, primitive or complex struct), 208 // removes element by index position removalIndex, 209 // and returns the reassembled result slice without the removed element 210 // 211 // note: this method does not preserve element ordering, this is in order to achieve faster call performance 212 // 213 // removalIndex = positive number indicates element removal index position (0-based index) 214 // 215 // negative number indicates element removal index from right, 216 // -1 = last element to remove; -2 = second to the last to remove, and so on 217 // positive / negative number out of bound = returns original slice unchanged 218 // 219 // if resultSlice is nil, then no slice remain 220 func SliceDeleteElement(slice interface{}, removalIndex int) (resultSlice interface{}) { 221 sliceObj := reflect.ValueOf(slice) 222 223 if sliceObj.Kind() == reflect.Ptr { 224 sliceObj = sliceObj.Elem() 225 } 226 227 if sliceObj.Kind() != reflect.Slice { 228 return nil 229 } 230 231 if removalIndex < 0 { 232 removalIndex = sliceObj.Len() - AbsInt(removalIndex) 233 234 if removalIndex < 0 { 235 return slice 236 } 237 } 238 239 if removalIndex > sliceObj.Len()-1 { 240 return slice 241 } 242 243 rm := sliceObj.Index(removalIndex) 244 last := sliceObj.Index(sliceObj.Len() - 1) 245 246 if rm.CanSet() { 247 rm.Set(last) 248 } else { 249 return slice 250 } 251 252 return sliceObj.Slice(0, sliceObj.Len()-1).Interface() 253 } 254 255 // ================================================================================================================ 256 // console helpers 257 // ================================================================================================================ 258 259 // ConsolePromptAndAnswer is a helper to prompt a message and then scan a response in console 260 func ConsolePromptAndAnswer(prompt string, replyLowercase bool, autoTrim ...bool) string { 261 fmt.Print(prompt) 262 263 answer := "" 264 265 if _, e := fmt.Scanln(&answer); e != nil { 266 answer = "" 267 fmt.Println() 268 } else { 269 answer = RightTrimLF(answer) 270 271 if replyLowercase { 272 answer = strings.ToLower(answer) 273 } 274 275 if len(autoTrim) > 0 { 276 if autoTrim[0] { 277 answer = Trim(answer) 278 } 279 } 280 281 fmt.Println() 282 } 283 284 return answer 285 } 286 287 // ConsolePromptAndAnswerBool is a helper to prompt a message and then scan a response in console 288 func ConsolePromptAndAnswerBool(prompt string, defaultTrue ...bool) bool { 289 fmt.Print(prompt) 290 291 answer := "" 292 result := false 293 defVal := false 294 295 if len(defaultTrue) > 0 { 296 if defaultTrue[0] { 297 defVal = true 298 } 299 } 300 301 if _, e := fmt.Scanln(&answer); e != nil { 302 fmt.Println() 303 return defVal 304 } else { 305 answer = RightTrimLF(answer) 306 307 if LenTrim(answer) > 0 { 308 result, _ = ParseBool(answer) 309 } else { 310 result = defVal 311 } 312 313 fmt.Println() 314 } 315 316 return result 317 } 318 319 // ConsolePromptAndAnswerInt is a helper to prompt a message and then scan a response in console 320 func ConsolePromptAndAnswerInt(prompt string, preventNegative ...bool) int { 321 fmt.Print(prompt) 322 323 answer := "" 324 result := 0 325 326 if _, e := fmt.Scanln(&answer); e != nil { 327 fmt.Println() 328 return 0 329 } else { 330 answer = RightTrimLF(answer) 331 result, _ = ParseInt32(answer) 332 333 if result < 0 { 334 if len(preventNegative) > 0 { 335 if preventNegative[0] { 336 result = 0 337 } 338 } 339 } 340 341 fmt.Println() 342 } 343 344 return result 345 } 346 347 // ConsolePromptAndAnswerFloat64 is a helper to prompt a message and then scan a response in console 348 func ConsolePromptAndAnswerFloat64(prompt string, preventNegative ...bool) float64 { 349 fmt.Print(prompt) 350 351 answer := "" 352 result := float64(0) 353 354 if _, e := fmt.Scanln(&answer); e != nil { 355 fmt.Println() 356 return 0 357 } else { 358 answer = RightTrimLF(answer) 359 result, _ = ParseFloat64(answer) 360 361 if result < 0 { 362 if len(preventNegative) > 0 { 363 if preventNegative[0] { 364 result = 0 365 } 366 } 367 } 368 369 fmt.Println() 370 } 371 372 return result 373 } 374 375 // ErrorMessage find the error cause time, file, code line number and error message 376 func ErrorMessage(err error) string { 377 378 _, file, line, _ := runtime.Caller(1) 379 indexFunc := func(file string) string { 380 backup := "/" + file 381 lastSlashIndex := strings.LastIndex(backup, "/") 382 if lastSlashIndex < 0 { 383 return backup 384 } 385 secondLastSlashIndex := strings.LastIndex(backup[:lastSlashIndex], "/") 386 if secondLastSlashIndex < 0 { 387 return backup[lastSlashIndex+1:] 388 } 389 return backup[secondLastSlashIndex+1:] 390 } 391 392 logmessage := fmt.Sprintf("%v %v:%v:%v", time.Now().UTC().Format("2006-01-02 15:04:05.000"), indexFunc(file), line, err.Error()) 393 394 return logmessage 395 }