github.com/gogf/gf@v1.16.9/container/garray/garray_normal_str.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 garray 8 9 import ( 10 "bytes" 11 "github.com/gogf/gf/errors/gcode" 12 "github.com/gogf/gf/errors/gerror" 13 "github.com/gogf/gf/internal/json" 14 "github.com/gogf/gf/text/gstr" 15 "math" 16 "sort" 17 "strings" 18 19 "github.com/gogf/gf/internal/rwmutex" 20 "github.com/gogf/gf/util/gconv" 21 "github.com/gogf/gf/util/grand" 22 ) 23 24 // StrArray is a golang string array with rich features. 25 // It contains a concurrent-safe/unsafe switch, which should be set 26 // when its initialization and cannot be changed then. 27 type StrArray struct { 28 mu rwmutex.RWMutex 29 array []string 30 } 31 32 // NewStrArray creates and returns an empty array. 33 // The parameter `safe` is used to specify whether using array in concurrent-safety, 34 // which is false in default. 35 func NewStrArray(safe ...bool) *StrArray { 36 return NewStrArraySize(0, 0, safe...) 37 } 38 39 // NewStrArraySize create and returns an array with given size and cap. 40 // The parameter `safe` is used to specify whether using array in concurrent-safety, 41 // which is false in default. 42 func NewStrArraySize(size int, cap int, safe ...bool) *StrArray { 43 return &StrArray{ 44 mu: rwmutex.Create(safe...), 45 array: make([]string, size, cap), 46 } 47 } 48 49 // NewStrArrayFrom creates and returns an array with given slice `array`. 50 // The parameter `safe` is used to specify whether using array in concurrent-safety, 51 // which is false in default. 52 func NewStrArrayFrom(array []string, safe ...bool) *StrArray { 53 return &StrArray{ 54 mu: rwmutex.Create(safe...), 55 array: array, 56 } 57 } 58 59 // NewStrArrayFromCopy creates and returns an array from a copy of given slice `array`. 60 // The parameter `safe` is used to specify whether using array in concurrent-safety, 61 // which is false in default. 62 func NewStrArrayFromCopy(array []string, safe ...bool) *StrArray { 63 newArray := make([]string, len(array)) 64 copy(newArray, array) 65 return &StrArray{ 66 mu: rwmutex.Create(safe...), 67 array: newArray, 68 } 69 } 70 71 // At returns the value by the specified index. 72 // If the given `index` is out of range of the array, it returns an empty string. 73 func (a *StrArray) At(index int) (value string) { 74 value, _ = a.Get(index) 75 return 76 } 77 78 // Get returns the value by the specified index. 79 // If the given `index` is out of range of the array, the `found` is false. 80 func (a *StrArray) Get(index int) (value string, found bool) { 81 a.mu.RLock() 82 defer a.mu.RUnlock() 83 if index < 0 || index >= len(a.array) { 84 return "", false 85 } 86 return a.array[index], true 87 } 88 89 // Set sets value to specified index. 90 func (a *StrArray) Set(index int, value string) error { 91 a.mu.Lock() 92 defer a.mu.Unlock() 93 if index < 0 || index >= len(a.array) { 94 return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) 95 } 96 a.array[index] = value 97 return nil 98 } 99 100 // SetArray sets the underlying slice array with the given `array`. 101 func (a *StrArray) SetArray(array []string) *StrArray { 102 a.mu.Lock() 103 defer a.mu.Unlock() 104 a.array = array 105 return a 106 } 107 108 // Replace replaces the array items by given `array` from the beginning of array. 109 func (a *StrArray) Replace(array []string) *StrArray { 110 a.mu.Lock() 111 defer a.mu.Unlock() 112 max := len(array) 113 if max > len(a.array) { 114 max = len(a.array) 115 } 116 for i := 0; i < max; i++ { 117 a.array[i] = array[i] 118 } 119 return a 120 } 121 122 // Sum returns the sum of values in an array. 123 func (a *StrArray) Sum() (sum int) { 124 a.mu.RLock() 125 defer a.mu.RUnlock() 126 for _, v := range a.array { 127 sum += gconv.Int(v) 128 } 129 return 130 } 131 132 // Sort sorts the array in increasing order. 133 // The parameter `reverse` controls whether sort 134 // in increasing order(default) or decreasing order 135 func (a *StrArray) Sort(reverse ...bool) *StrArray { 136 a.mu.Lock() 137 defer a.mu.Unlock() 138 if len(reverse) > 0 && reverse[0] { 139 sort.Slice(a.array, func(i, j int) bool { 140 return strings.Compare(a.array[i], a.array[j]) >= 0 141 }) 142 } else { 143 sort.Strings(a.array) 144 } 145 return a 146 } 147 148 // SortFunc sorts the array by custom function `less`. 149 func (a *StrArray) SortFunc(less func(v1, v2 string) bool) *StrArray { 150 a.mu.Lock() 151 defer a.mu.Unlock() 152 sort.Slice(a.array, func(i, j int) bool { 153 return less(a.array[i], a.array[j]) 154 }) 155 return a 156 } 157 158 // InsertBefore inserts the `value` to the front of `index`. 159 func (a *StrArray) InsertBefore(index int, value string) error { 160 a.mu.Lock() 161 defer a.mu.Unlock() 162 if index < 0 || index >= len(a.array) { 163 return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) 164 } 165 rear := append([]string{}, a.array[index:]...) 166 a.array = append(a.array[0:index], value) 167 a.array = append(a.array, rear...) 168 return nil 169 } 170 171 // InsertAfter inserts the `value` to the back of `index`. 172 func (a *StrArray) InsertAfter(index int, value string) error { 173 a.mu.Lock() 174 defer a.mu.Unlock() 175 if index < 0 || index >= len(a.array) { 176 return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) 177 } 178 rear := append([]string{}, a.array[index+1:]...) 179 a.array = append(a.array[0:index+1], value) 180 a.array = append(a.array, rear...) 181 return nil 182 } 183 184 // Remove removes an item by index. 185 // If the given `index` is out of range of the array, the `found` is false. 186 func (a *StrArray) Remove(index int) (value string, found bool) { 187 a.mu.Lock() 188 defer a.mu.Unlock() 189 return a.doRemoveWithoutLock(index) 190 } 191 192 // doRemoveWithoutLock removes an item by index without lock. 193 func (a *StrArray) doRemoveWithoutLock(index int) (value string, found bool) { 194 if index < 0 || index >= len(a.array) { 195 return "", false 196 } 197 // Determine array boundaries when deleting to improve deletion efficiency. 198 if index == 0 { 199 value := a.array[0] 200 a.array = a.array[1:] 201 return value, true 202 } else if index == len(a.array)-1 { 203 value := a.array[index] 204 a.array = a.array[:index] 205 return value, true 206 } 207 // If it is a non-boundary delete, 208 // it will involve the creation of an array, 209 // then the deletion is less efficient. 210 value = a.array[index] 211 a.array = append(a.array[:index], a.array[index+1:]...) 212 return value, true 213 } 214 215 // RemoveValue removes an item by value. 216 // It returns true if value is found in the array, or else false if not found. 217 func (a *StrArray) RemoveValue(value string) bool { 218 if i := a.Search(value); i != -1 { 219 _, found := a.Remove(i) 220 return found 221 } 222 return false 223 } 224 225 // PushLeft pushes one or multiple items to the beginning of array. 226 func (a *StrArray) PushLeft(value ...string) *StrArray { 227 a.mu.Lock() 228 a.array = append(value, a.array...) 229 a.mu.Unlock() 230 return a 231 } 232 233 // PushRight pushes one or multiple items to the end of array. 234 // It equals to Append. 235 func (a *StrArray) PushRight(value ...string) *StrArray { 236 a.mu.Lock() 237 a.array = append(a.array, value...) 238 a.mu.Unlock() 239 return a 240 } 241 242 // PopLeft pops and returns an item from the beginning of array. 243 // Note that if the array is empty, the `found` is false. 244 func (a *StrArray) PopLeft() (value string, found bool) { 245 a.mu.Lock() 246 defer a.mu.Unlock() 247 if len(a.array) == 0 { 248 return "", false 249 } 250 value = a.array[0] 251 a.array = a.array[1:] 252 return value, true 253 } 254 255 // PopRight pops and returns an item from the end of array. 256 // Note that if the array is empty, the `found` is false. 257 func (a *StrArray) PopRight() (value string, found bool) { 258 a.mu.Lock() 259 defer a.mu.Unlock() 260 index := len(a.array) - 1 261 if index < 0 { 262 return "", false 263 } 264 value = a.array[index] 265 a.array = a.array[:index] 266 return value, true 267 } 268 269 // PopRand randomly pops and return an item out of array. 270 // Note that if the array is empty, the `found` is false. 271 func (a *StrArray) PopRand() (value string, found bool) { 272 a.mu.Lock() 273 defer a.mu.Unlock() 274 return a.doRemoveWithoutLock(grand.Intn(len(a.array))) 275 } 276 277 // PopRands randomly pops and returns `size` items out of array. 278 // If the given `size` is greater than size of the array, it returns all elements of the array. 279 // Note that if given `size` <= 0 or the array is empty, it returns nil. 280 func (a *StrArray) PopRands(size int) []string { 281 a.mu.Lock() 282 defer a.mu.Unlock() 283 if size <= 0 || len(a.array) == 0 { 284 return nil 285 } 286 if size >= len(a.array) { 287 size = len(a.array) 288 } 289 array := make([]string, size) 290 for i := 0; i < size; i++ { 291 array[i], _ = a.doRemoveWithoutLock(grand.Intn(len(a.array))) 292 } 293 return array 294 } 295 296 // PopLefts pops and returns `size` items from the beginning of array. 297 // If the given `size` is greater than size of the array, it returns all elements of the array. 298 // Note that if given `size` <= 0 or the array is empty, it returns nil. 299 func (a *StrArray) PopLefts(size int) []string { 300 a.mu.Lock() 301 defer a.mu.Unlock() 302 if size <= 0 || len(a.array) == 0 { 303 return nil 304 } 305 if size >= len(a.array) { 306 array := a.array 307 a.array = a.array[:0] 308 return array 309 } 310 value := a.array[0:size] 311 a.array = a.array[size:] 312 return value 313 } 314 315 // PopRights pops and returns `size` items from the end of array. 316 // If the given `size` is greater than size of the array, it returns all elements of the array. 317 // Note that if given `size` <= 0 or the array is empty, it returns nil. 318 func (a *StrArray) PopRights(size int) []string { 319 a.mu.Lock() 320 defer a.mu.Unlock() 321 if size <= 0 || len(a.array) == 0 { 322 return nil 323 } 324 index := len(a.array) - size 325 if index <= 0 { 326 array := a.array 327 a.array = a.array[:0] 328 return array 329 } 330 value := a.array[index:] 331 a.array = a.array[:index] 332 return value 333 } 334 335 // Range picks and returns items by range, like array[start:end]. 336 // Notice, if in concurrent-safe usage, it returns a copy of slice; 337 // else a pointer to the underlying data. 338 // 339 // If `end` is negative, then the offset will start from the end of array. 340 // If `end` is omitted, then the sequence will have everything from start up 341 // until the end of the array. 342 func (a *StrArray) Range(start int, end ...int) []string { 343 a.mu.RLock() 344 defer a.mu.RUnlock() 345 offsetEnd := len(a.array) 346 if len(end) > 0 && end[0] < offsetEnd { 347 offsetEnd = end[0] 348 } 349 if start > offsetEnd { 350 return nil 351 } 352 if start < 0 { 353 start = 0 354 } 355 array := ([]string)(nil) 356 if a.mu.IsSafe() { 357 array = make([]string, offsetEnd-start) 358 copy(array, a.array[start:offsetEnd]) 359 } else { 360 array = a.array[start:offsetEnd] 361 } 362 return array 363 } 364 365 // SubSlice returns a slice of elements from the array as specified 366 // by the `offset` and `size` parameters. 367 // If in concurrent safe usage, it returns a copy of the slice; else a pointer. 368 // 369 // If offset is non-negative, the sequence will start at that offset in the array. 370 // If offset is negative, the sequence will start that far from the end of the array. 371 // 372 // If length is given and is positive, then the sequence will have up to that many elements in it. 373 // If the array is shorter than the length, then only the available array elements will be present. 374 // If length is given and is negative then the sequence will stop that many elements from the end of the array. 375 // If it is omitted, then the sequence will have everything from offset up until the end of the array. 376 // 377 // Any possibility crossing the left border of array, it will fail. 378 func (a *StrArray) SubSlice(offset int, length ...int) []string { 379 a.mu.RLock() 380 defer a.mu.RUnlock() 381 size := len(a.array) 382 if len(length) > 0 { 383 size = length[0] 384 } 385 if offset > len(a.array) { 386 return nil 387 } 388 if offset < 0 { 389 offset = len(a.array) + offset 390 if offset < 0 { 391 return nil 392 } 393 } 394 if size < 0 { 395 offset += size 396 size = -size 397 if offset < 0 { 398 return nil 399 } 400 } 401 end := offset + size 402 if end > len(a.array) { 403 end = len(a.array) 404 size = len(a.array) - offset 405 } 406 if a.mu.IsSafe() { 407 s := make([]string, size) 408 copy(s, a.array[offset:]) 409 return s 410 } else { 411 return a.array[offset:end] 412 } 413 } 414 415 // Append is alias of PushRight,please See PushRight. 416 func (a *StrArray) Append(value ...string) *StrArray { 417 a.mu.Lock() 418 a.array = append(a.array, value...) 419 a.mu.Unlock() 420 return a 421 } 422 423 // Len returns the length of array. 424 func (a *StrArray) Len() int { 425 a.mu.RLock() 426 length := len(a.array) 427 a.mu.RUnlock() 428 return length 429 } 430 431 // Slice returns the underlying data of array. 432 // Note that, if it's in concurrent-safe usage, it returns a copy of underlying data, 433 // or else a pointer to the underlying data. 434 func (a *StrArray) Slice() []string { 435 array := ([]string)(nil) 436 if a.mu.IsSafe() { 437 a.mu.RLock() 438 defer a.mu.RUnlock() 439 array = make([]string, len(a.array)) 440 copy(array, a.array) 441 } else { 442 array = a.array 443 } 444 return array 445 } 446 447 // Interfaces returns current array as []interface{}. 448 func (a *StrArray) Interfaces() []interface{} { 449 a.mu.RLock() 450 defer a.mu.RUnlock() 451 array := make([]interface{}, len(a.array)) 452 for k, v := range a.array { 453 array[k] = v 454 } 455 return array 456 } 457 458 // Clone returns a new array, which is a copy of current array. 459 func (a *StrArray) Clone() (newArray *StrArray) { 460 a.mu.RLock() 461 array := make([]string, len(a.array)) 462 copy(array, a.array) 463 a.mu.RUnlock() 464 return NewStrArrayFrom(array, a.mu.IsSafe()) 465 } 466 467 // Clear deletes all items of current array. 468 func (a *StrArray) Clear() *StrArray { 469 a.mu.Lock() 470 if len(a.array) > 0 { 471 a.array = make([]string, 0) 472 } 473 a.mu.Unlock() 474 return a 475 } 476 477 // Contains checks whether a value exists in the array. 478 func (a *StrArray) Contains(value string) bool { 479 return a.Search(value) != -1 480 } 481 482 // ContainsI checks whether a value exists in the array with case-insensitively. 483 // Note that it internally iterates the whole array to do the comparison with case-insensitively. 484 func (a *StrArray) ContainsI(value string) bool { 485 a.mu.RLock() 486 defer a.mu.RUnlock() 487 if len(a.array) == 0 { 488 return false 489 } 490 for _, v := range a.array { 491 if strings.EqualFold(v, value) { 492 return true 493 } 494 } 495 return false 496 } 497 498 // Search searches array by `value`, returns the index of `value`, 499 // or returns -1 if not exists. 500 func (a *StrArray) Search(value string) int { 501 a.mu.RLock() 502 defer a.mu.RUnlock() 503 if len(a.array) == 0 { 504 return -1 505 } 506 result := -1 507 for index, v := range a.array { 508 if strings.Compare(v, value) == 0 { 509 result = index 510 break 511 } 512 } 513 return result 514 } 515 516 // Unique uniques the array, clear repeated items. 517 // Example: [1,1,2,3,2] -> [1,2,3] 518 func (a *StrArray) Unique() *StrArray { 519 a.mu.Lock() 520 for i := 0; i < len(a.array)-1; i++ { 521 for j := i + 1; j < len(a.array); { 522 if a.array[i] == a.array[j] { 523 a.array = append(a.array[:j], a.array[j+1:]...) 524 } else { 525 j++ 526 } 527 } 528 } 529 a.mu.Unlock() 530 return a 531 } 532 533 // LockFunc locks writing by callback function `f`. 534 func (a *StrArray) LockFunc(f func(array []string)) *StrArray { 535 a.mu.Lock() 536 defer a.mu.Unlock() 537 f(a.array) 538 return a 539 } 540 541 // RLockFunc locks reading by callback function `f`. 542 func (a *StrArray) RLockFunc(f func(array []string)) *StrArray { 543 a.mu.RLock() 544 defer a.mu.RUnlock() 545 f(a.array) 546 return a 547 } 548 549 // Merge merges `array` into current array. 550 // The parameter `array` can be any garray or slice type. 551 // The difference between Merge and Append is Append supports only specified slice type, 552 // but Merge supports more parameter types. 553 func (a *StrArray) Merge(array interface{}) *StrArray { 554 return a.Append(gconv.Strings(array)...) 555 } 556 557 // Fill fills an array with num entries of the value `value`, 558 // keys starting at the `startIndex` parameter. 559 func (a *StrArray) Fill(startIndex int, num int, value string) error { 560 a.mu.Lock() 561 defer a.mu.Unlock() 562 if startIndex < 0 || startIndex > len(a.array) { 563 return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", startIndex, len(a.array)) 564 } 565 for i := startIndex; i < startIndex+num; i++ { 566 if i > len(a.array)-1 { 567 a.array = append(a.array, value) 568 } else { 569 a.array[i] = value 570 } 571 } 572 return nil 573 } 574 575 // Chunk splits an array into multiple arrays, 576 // the size of each array is determined by `size`. 577 // The last chunk may contain less than size elements. 578 func (a *StrArray) Chunk(size int) [][]string { 579 if size < 1 { 580 return nil 581 } 582 a.mu.RLock() 583 defer a.mu.RUnlock() 584 length := len(a.array) 585 chunks := int(math.Ceil(float64(length) / float64(size))) 586 var n [][]string 587 for i, end := 0, 0; chunks > 0; chunks-- { 588 end = (i + 1) * size 589 if end > length { 590 end = length 591 } 592 n = append(n, a.array[i*size:end]) 593 i++ 594 } 595 return n 596 } 597 598 // Pad pads array to the specified length with `value`. 599 // If size is positive then the array is padded on the right, or negative on the left. 600 // If the absolute value of `size` is less than or equal to the length of the array 601 // then no padding takes place. 602 func (a *StrArray) Pad(size int, value string) *StrArray { 603 a.mu.Lock() 604 defer a.mu.Unlock() 605 if size == 0 || (size > 0 && size < len(a.array)) || (size < 0 && size > -len(a.array)) { 606 return a 607 } 608 n := size 609 if size < 0 { 610 n = -size 611 } 612 n -= len(a.array) 613 tmp := make([]string, n) 614 for i := 0; i < n; i++ { 615 tmp[i] = value 616 } 617 if size > 0 { 618 a.array = append(a.array, tmp...) 619 } else { 620 a.array = append(tmp, a.array...) 621 } 622 return a 623 } 624 625 // Rand randomly returns one item from array(no deleting). 626 func (a *StrArray) Rand() (value string, found bool) { 627 a.mu.RLock() 628 defer a.mu.RUnlock() 629 if len(a.array) == 0 { 630 return "", false 631 } 632 return a.array[grand.Intn(len(a.array))], true 633 } 634 635 // Rands randomly returns `size` items from array(no deleting). 636 func (a *StrArray) Rands(size int) []string { 637 a.mu.RLock() 638 defer a.mu.RUnlock() 639 if size <= 0 || len(a.array) == 0 { 640 return nil 641 } 642 array := make([]string, size) 643 for i := 0; i < size; i++ { 644 array[i] = a.array[grand.Intn(len(a.array))] 645 } 646 return array 647 } 648 649 // Shuffle randomly shuffles the array. 650 func (a *StrArray) Shuffle() *StrArray { 651 a.mu.Lock() 652 defer a.mu.Unlock() 653 for i, v := range grand.Perm(len(a.array)) { 654 a.array[i], a.array[v] = a.array[v], a.array[i] 655 } 656 return a 657 } 658 659 // Reverse makes array with elements in reverse order. 660 func (a *StrArray) Reverse() *StrArray { 661 a.mu.Lock() 662 defer a.mu.Unlock() 663 for i, j := 0, len(a.array)-1; i < j; i, j = i+1, j-1 { 664 a.array[i], a.array[j] = a.array[j], a.array[i] 665 } 666 return a 667 } 668 669 // Join joins array elements with a string `glue`. 670 func (a *StrArray) Join(glue string) string { 671 a.mu.RLock() 672 defer a.mu.RUnlock() 673 if len(a.array) == 0 { 674 return "" 675 } 676 buffer := bytes.NewBuffer(nil) 677 for k, v := range a.array { 678 buffer.WriteString(v) 679 if k != len(a.array)-1 { 680 buffer.WriteString(glue) 681 } 682 } 683 return buffer.String() 684 } 685 686 // CountValues counts the number of occurrences of all values in the array. 687 func (a *StrArray) CountValues() map[string]int { 688 m := make(map[string]int) 689 a.mu.RLock() 690 defer a.mu.RUnlock() 691 for _, v := range a.array { 692 m[v]++ 693 } 694 return m 695 } 696 697 // Iterator is alias of IteratorAsc. 698 func (a *StrArray) Iterator(f func(k int, v string) bool) { 699 a.IteratorAsc(f) 700 } 701 702 // IteratorAsc iterates the array readonly in ascending order with given callback function `f`. 703 // If `f` returns true, then it continues iterating; or false to stop. 704 func (a *StrArray) IteratorAsc(f func(k int, v string) bool) { 705 a.mu.RLock() 706 defer a.mu.RUnlock() 707 for k, v := range a.array { 708 if !f(k, v) { 709 break 710 } 711 } 712 } 713 714 // IteratorDesc iterates the array readonly in descending order with given callback function `f`. 715 // If `f` returns true, then it continues iterating; or false to stop. 716 func (a *StrArray) IteratorDesc(f func(k int, v string) bool) { 717 a.mu.RLock() 718 defer a.mu.RUnlock() 719 for i := len(a.array) - 1; i >= 0; i-- { 720 if !f(i, a.array[i]) { 721 break 722 } 723 } 724 } 725 726 // String returns current array as a string, which implements like json.Marshal does. 727 func (a *StrArray) String() string { 728 a.mu.RLock() 729 defer a.mu.RUnlock() 730 buffer := bytes.NewBuffer(nil) 731 buffer.WriteByte('[') 732 for k, v := range a.array { 733 buffer.WriteString(`"` + gstr.QuoteMeta(v, `"\`) + `"`) 734 if k != len(a.array)-1 { 735 buffer.WriteByte(',') 736 } 737 } 738 buffer.WriteByte(']') 739 return buffer.String() 740 } 741 742 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 743 // Note that do not use pointer as its receiver here. 744 func (a StrArray) MarshalJSON() ([]byte, error) { 745 a.mu.RLock() 746 defer a.mu.RUnlock() 747 return json.Marshal(a.array) 748 } 749 750 // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. 751 func (a *StrArray) UnmarshalJSON(b []byte) error { 752 if a.array == nil { 753 a.array = make([]string, 0) 754 } 755 a.mu.Lock() 756 defer a.mu.Unlock() 757 if err := json.UnmarshalUseNumber(b, &a.array); err != nil { 758 return err 759 } 760 return nil 761 } 762 763 // UnmarshalValue is an interface implement which sets any type of value for array. 764 func (a *StrArray) UnmarshalValue(value interface{}) error { 765 a.mu.Lock() 766 defer a.mu.Unlock() 767 switch value.(type) { 768 case string, []byte: 769 return json.UnmarshalUseNumber(gconv.Bytes(value), &a.array) 770 default: 771 a.array = gconv.SliceStr(value) 772 } 773 return nil 774 } 775 776 // FilterEmpty removes all empty string value of the array. 777 func (a *StrArray) FilterEmpty() *StrArray { 778 a.mu.Lock() 779 defer a.mu.Unlock() 780 for i := 0; i < len(a.array); { 781 if a.array[i] == "" { 782 a.array = append(a.array[:i], a.array[i+1:]...) 783 } else { 784 i++ 785 } 786 } 787 return a 788 } 789 790 // Walk applies a user supplied function `f` to every item of array. 791 func (a *StrArray) Walk(f func(value string) string) *StrArray { 792 a.mu.Lock() 793 defer a.mu.Unlock() 794 for i, v := range a.array { 795 a.array[i] = f(v) 796 } 797 return a 798 } 799 800 // IsEmpty checks whether the array is empty. 801 func (a *StrArray) IsEmpty() bool { 802 return a.Len() == 0 803 }