Hacker News new | ask | show | jobs
by Thorrez 629 days ago
This will wait up to 1 second before showing a result when a result comes in. I'm pretty sure Chris doesn't want any waiting like that.

This will also print some results multiple times. I think Chris wants to print each result once.

1 comments

It is utterly clear that the random wait is not intrinsic to the logic - it was only added for demonstration to simulate varying duration of requests.

You can simply comment out the println and just pick the first results[0]. Again, the repeated println for all results was only added for demonstrative clarity.

Frankly, the above satisfies all primary goals. The rest is just nitpicking - without a formal specification of the problem one can argue all day.

>It is utterly clear that the random wait is not intrinsic to the logic - it was only added for demonstration to simulate varying duration of requests.

I wasn't talking about the random wait at all. I was talking about

      for range time.NewTicker(time.Second).C {
       fmt.Println("Results: ", results)
      }
>You can simply comment out the println and just pick the first results[0].

When should we look at results[0]? There needs to be some notification that results[0] is ready to be looked at. Similarly with all the rest of the results.

>Frankly, the above satisfies all primary goals. The rest is just nitpicking - without a formal specification of the problem one can argue all day.

I guess we have to disagree. From my reading of the blog post it was pretty clear what Chris wanted, and the code you provided didn't meet that.

You can completely ignore that pretty print function as it not essential to the goal.

Revised example without pretty-print at https://go.dev/play/p/LkAT_g95BLO

As soon as you have completed `<-finished` in the main go-routine, it means `results[0]` has been populated and is ready for read.

If you want to wait till all results are available, then perform `<-finished`, `len(results)` times. (Or use sync.WaitGroup)

    package main

    import (
     "fmt"
     "math/rand"
     "sync/atomic"
     "time"
    )

    func main() {
     args := []int{5, 2, 4, 1, 8}
     var resultCount atomic.Int32
     resultCount.Store(-1)
     results := make([]int, len(args))
     finished := make(chan bool, len(args))

     slowSquare := func(arg int, fnNum int) {
      randomMilliseconds := rand.Intn(1000)
      blockDuration := time.Duration(randomMilliseconds) * time.Millisecond
      fmt.Printf("(#%d) Squaring %d, Blocking for %d milliseconds...\n", fnNum, arg, randomMilliseconds)
      <-time.After(blockDuration)
      resultIndex := resultCount.Add(1)
      results[resultIndex] = arg * arg
      fmt.Printf("(#%d) Squared %d: results[%d]=%d\n", fnNum, arg, resultIndex, results[resultIndex])
      finished <- true
     }

     for i, x := range args {
      go slowSquare(x, i)
     }
     fmt.Println("(main) Waiting for first finish")
     <-finished
     fmt.Println("(main) First Result: ", results[0])
    }
Chris wants to report the results in the same order as the inputs. So 25, 4, 16, 1, 64. Your code will report the results in an arbitrary order.
Ok, but that is even more simpler and shorter with plain `sync.WaitGroup`.

    package main

    import (
     "fmt"
     "math/rand"
     "sync"
     "time"
    )

    func main() {
     args := []int{5, 2, 4, 1, 8}
     results := make([]int, len(args))
     var wg sync.WaitGroup

     slowSquare := func(arg int, resultIndex int) {
      randomMilliseconds := rand.Intn(1000)
      blockDuration := time.Duration(randomMilliseconds) * time.Millisecond
      fmt.Printf("(#%d) Squaring %d, Blocking for %d milliseconds...\n", resultIndex, arg, randomMilliseconds)
      <-time.After(blockDuration)
      results[resultIndex] = arg * arg
      fmt.Printf("(#%d) Squared %d: results[%d]=%d\n", resultIndex, arg, resultIndex, results[resultIndex])
      wg.Done()
     }

     for i, x := range args {
      wg.Add(1)
      go slowSquare(x, i)
     }
     fmt.Println("(main) Waiting for all to finish")
     wg.Wait()
     fmt.Println("(main) Results: ", results)
    }


    (main) Waiting for all to finish
    (#4) Squaring 8, Blocking for 574 milliseconds...
    (#1) Squaring 2, Blocking for 998 milliseconds...
    (#2) Squaring 4, Blocking for 197 milliseconds...
    (#3) Squaring 1, Blocking for 542 milliseconds...
    (#0) Squaring 5, Blocking for 12 milliseconds...
    (#0) Squared 5: results[0]=25
    (#2) Squared 4: results[2]=16
    (#3) Squared 1: results[3]=1
    (#4) Squared 8: results[4]=64
    (#1) Squared 2: results[1]=4
    (main) Results: [25 4 16 1 64]
As soon as results[0] is ready he wants to print it. Then as soon as results[1] is read he wants to print it. Etc. Not waiting till the end to print everything, and not printing anything out of order.