* Unknown User <knowsuperunkn...@gmail.com> [160920 06:43]:
> Hi All,
> 
> I am trying to print the contents of  a file randomizing the lines.
> The following code works, but does not exit even after all the lines are 
> read.
> What needs to be done to correct it?

Try this <https://play.golang.org/p/Vg6f0gSs3l>

package main

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

func main() {
    filename := os.Args[1]
    if filename == "" {
        panic("No filename")
    }
    fh,err := os.Open(filename)
    if err != nil {
        panic(err)
    }
    scanner := bufio.NewScanner(fh)
    c := make(chan string)
    var wg sync.WaitGroup
    for scanner.Scan() {
        line := scanner.Text()
        wg.Add(1)
        go func(l string){
            time.Sleep(time.Duration(rand.Intn(30)) * time.Millisecond)
            c <-  l
            wg.Done()
        }(line)
    }
    go func() {
        wg.Wait()
        close(c)
    }()
    for  {
        myline, ok := <-c
        if !ok {
            return
        }
        fmt.Println(myline)
    }
}

You need a way to determine when all of the spawned goroutines have sent
their line to the channel so you know when to exit the bottom for loop.
A select doesn't help, because the goroutines are sending on the channel
at random intervals, so the default case will cause a busy loop between
sends, not just after all sends have completed.

The WaitGroup keeps track of how many worker goroutines have not yet
finished.  The final goroutine (started below the top for loop) waits
for all the workers to finish, then closes the channel.

The bottom for loop does not use a select statement; it merely reads
from the channel, which will block until the next worker sends its line.
When the final goroutine closes the channel, the channel read will
return "", false, and the bottom for loop will exit.

As a general rule of thumb, use a select only when you have more than
one channel send and/or receive that you want to wait for, and only use
a default case when you have other work that can be done if the channel
operations are all blocked (waiting).  Don't use default in an otherwise
empty for loop around a select.

hth...Marvin

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to