1

Hello here's my sample go playground https://go.dev/play/p/dUUsf6OXt1x

input := []int{1, 2, 3, 4, 5, 6, 7, 8}

wg := sync.WaitGroup{}

var result []int

for i, num := range input {
    wg.Add(1)
    go func(num, i int) {
        if num%2 == 0 {
            result = append(result, num)
        }

        wg.Done()
    }(num, i)
}
wg.Wait()

fmt.Println(result)

My goal result : 2,4,6,8 in the right order

Unfortunately on my code because I am appending instead of assigning to specific slice index, I sometimes lose data (due to data race) and receive the result in an improper order.

The problem is the input is dynamic, it has a limitless count and I have no idea how many of the values of input will not pass the filtering of num%2 == 0

Can you please guide me how to concurrently append the filtered result while preserving the order and all of data

yssachan
  • 109
  • 7
  • 2
    You can use a mutex to avoid the data race, or, as an alternative, do the append in a single goroutine that receives the filtered results through a channel. The order could be managed by remembering the `i` of those `num` values that passed the filter. – mkopriva Oct 14 '22 at 06:06
  • 1
    ordered results you need defeats the purpose of concurrency, if you need ordered results you should not use the go routines – Yadu Oct 14 '22 at 06:13
  • 1
    Your requirements "concurrent" and "strict order" and "no data race" contradict each other. Redesign. – Volker Oct 14 '22 at 06:16
  • 2
    "Concurrent" and "strict order" contradict each other *only* if by order one means order-of-execution. OP however seems to be talking about the order of the output. Utilizing concurrency for long running processes while remembering the order of the incoming values is not an unreasonable requirement. Of course if the actual input was a sequence of incremental integers then the output could simply be sorted post-processing. But in cases where the incoming values aren't easily sortable, then one could retain the `i` of each value being processed to manage the order of the output. – mkopriva Oct 14 '22 at 06:31
  • Hi @mkopriva thank you for your suggestion, can you pls check the answer page if that is what you meant? thank you And right, what I need is the correct order of output not execution. – yssachan Oct 14 '22 at 07:27

1 Answers1

1

Based on @mkopriva's suggestion

I solve this by the ff : Unfortunately I have 2 loops instead of 1 and I cannot concurrent with the 2nd one because I will have the same problem as the first one.

events := []int{1, 2, 3, 4, 5, 6, 7, 8}
channels := make([]chan *int, 0)

// start concurrently
for _, event := range events {
    channel := make(chan *int)
    go response(event, channel)

    channels = append(channels, channel)

}

// collect response
var response []int

for i := range channels {

    result := *<-channels[i]
    if result%2 == 0 {

        response = append(response, result)

    }

}

// print response
log.Printf("channel response %v", response)

Go playground: https://go.dev/play/p/gW7nNireNLS

Hmmmm is this the best way?

yssachan
  • 109
  • 7
  • 1
    https://go.dev/play/p/0ZQuLC_A22R – mkopriva Oct 14 '22 at 08:21
  • 1
    Hi @mkopriva thank you so much. I really appreciate your comments on the go playground. I understand quickly your code. Sorry for taking so much of your time. You are such a blessing – yssachan Oct 14 '22 at 09:25