github.com/searKing/golang/go@v1.2.74/container/slice/findanyindex.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package slice 6 7 import ( 8 "sync" 9 10 "github.com/searKing/golang/go/util/object" 11 ) 12 13 // FindAnyFunc returns an {@link interface{}} describing some element of the stream, or an 14 // empty {@code Optional} if the stream is empty. 15 func FindAnyIndexFunc(s interface{}, f func(interface{}) bool) int { 16 return findAnyIndexFunc(Of(s), f, true) 17 } 18 19 // findAnyFunc is the same as FindAnyFunc. 20 func findAnyIndexFunc(s []interface{}, f func(interface{}) bool, truth bool) int { 21 object.RequireNonNil(s, "findAnyIndexFunc called on nil slice") 22 object.RequireNonNil(f, "findAnyIndexFunc called on nil callfn") 23 var findc chan int 24 findc = make(chan int) 25 defer close(findc) 26 var mu sync.Mutex 27 var wg sync.WaitGroup 28 var found bool 29 hasFound := func() bool { 30 mu.Lock() 31 defer mu.Unlock() 32 return found 33 } 34 for idx, r := range s { 35 if hasFound() { 36 break 37 } 38 39 wg.Add(1) 40 go func(rr interface{}) { 41 defer wg.Done() 42 foundYet := func() bool { 43 mu.Lock() 44 defer mu.Unlock() 45 return found 46 }() 47 if foundYet { 48 return 49 } 50 if f(rr) == truth { 51 mu.Lock() 52 defer mu.Unlock() 53 if found { 54 return 55 } 56 found = true 57 findc <- idx 58 return 59 } 60 }(r) 61 } 62 go func() { 63 defer close(findc) 64 wg.Done() 65 }() 66 out, ok := <-findc 67 if ok { 68 return out 69 } 70 return -1 71 }