#Is it Guaranteed that I will get the correct data?

7 messages · Page 1 of 1 (latest)

signal sable
#

I recently started using channels and concurrecny in Go and updated a project's code to this:

    c := make(chan []MetaFollow, 3)
    var wg sync.WaitGroup

    wg.Add(3)
    go Mutuals(followers, following, c, &wg)
    mutuals := <-c

    go IDontFollow(followers, following, c, &wg)
    iDontFollow := <-c

    go TheyDontFollow(followers, following, c, &wg)
    theyDontFollow := <-c
    wg.Wait()

How does Go ensures that the variable gets the exact same data as generated by it's above function? In the buffered channel case.

#

As per my knowlede, if I create an unbuffered channel i.e. c := make(chan []MetaFollow), the code will look concurrent but won't be executed concurrently. Since the other two tasks will be blocked to write to until the data is written by the first one. Am I correct?

#

So, ignoring the variable footprint, I could create a single size 3 buffered channel or 3 unbuffered channel c1, c2, c3.

Option 1 looks clean, but does it ensures that data gets stored where it needs to be (*How does Go ensures that the variable gets the exact same data as generated by it's above function? *)

But Option 2 looks more reliable.

Which is better?

raw kestrel
# signal sable I recently started using channels and concurrecny in Go and updated a project's ...

Your example is an abuse about goroutine

    c := make(chan []MetaFollow, 3)
    var wg sync.WaitGroup

    wg.Add(3)
    go Mutuals(followers, following, c, &wg)
    mutuals := <-c // the program will wait here until there is any data written into channel c

    // before Mutuals method send anything though c, IDontFollow won't be executed
    go IDontFollow(followers, following, c, &wg)
    iDontFollow := <-c // same as above

    // ...
    go TheyDontFollow(followers, following, c, &wg)
    theyDontFollow := <-c
    wg.Wait()
#

Then your Option 1 does not exists, because it just a more complexed synchronization process, but you want they do concurrently.

#

However, there are still two options if you want get the results of concurrent invokes:

func option1(){
  results := make([]ResultType, 3)
  var wg sync.WaitGroup
  wg.Add(1)
  go func(){
    defer wg.Done()
    results[0] = aFunction(args...)
  }()
  wg.Add(1)
  go func(){
    defer wg.Done()
    results[1] = aFunction(args...)
  }()
  wg.Add(1)
  go func(){
    defer wg.Done()
    results[2] = aFunction(args...)
  }()
  wg.Wait()
  // do sth with results
}
func option2(){
  resultsCh := make([]chan ResultType, 3)
  for i, _ := range results {
    resultsCh[i] = make(chan ResultType, 1)
  }
  go func(){
    resultsCh[0] <- aFunction(args...)
  }()
  go func(){
    resultsCh[1] <- aFunction(args...)
  }()
  go func(){
    resultsCh[2] <- aFunction(args...)
  }()
  for _, ch := range resultsCh {
    result := <-ch
    // do sth with the result
  }
}
signal sable
#

Thanks, in my use case Option 2 seems to give better faster results.