stian
stian

Reputation: 1987

How do I use Go routines in this example?

I have the following code snippet. I create a channel that takes 15 filenames at most from a given directory. I thought that I could create goroutines where one produces entries on a channel, and another consumes them. The consumer should print things taken from the channel.

My program executes without printing and I suspect that this is because the consumer routine is sleeping - isn't a new go routine started for each iteration of the for-loop? Shouldn't there eventually be something to print from the channel?

func (u* uniprot) produce(n string) {
    u.namesInDir <- n
}   

func (u* uniprot) consume() {
    fmt.println(<-u.namesInDir)
}       

func (u* uniprot) readFilenames(dirname string) {
    u.namesInDir = make(chan string, 15)
    dir, err := os.Open(dirname)
    errorCheck(err) 
    names, err := dir.Readdirnames(0)
    errorCheck(err)
    for _, n := range names {
        go u.produce(n)
        go u.consume()
    }
}

Upvotes: 0

Views: 190

Answers (1)

Nick Craig-Wood
Nick Craig-Wood

Reputation: 54117

You need to wait for the go routines to finish.

To see the problem put a time.Sleep at the end of the for loop.

To fix properly use a sync.WaitGroup

Here is an example of how it might work (untested)

import "sync"

func (u *uniprot) produce(n string, wg *sync.WaitGroup) {
    defer wg.Done()
    u.namesInDir <- n
}

func (u *uniprot) consume(wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.println(<-u.namesInDir)
}

func (u *uniprot) readFilenames(dirname string) {
    u.namesInDir = make(chan string, 15)
    dir, err := os.Open(dirname)
    errorCheck(err)
    names, err := dir.Readdirnames(0)
    errorCheck(err)
    wg := new(sync.WaitGroup)
    for _, n := range names {
        wg.Add(2)
        go u.produce(n, wg)
        go u.consume(wg)
    }
    wg.Wait()
}

Upvotes: 5

Related Questions