Home > front end >  collect data from channel while waiting for command to complete its execution in golang
collect data from channel while waiting for command to complete its execution in golang

Time:08-11

I am starting and a command execution which triggers a service which sends results on a channel (resChan), now i have to collect the results that i receive on this channel while command is executing, i don't have the len of how much data objects will arrive on resChan.

//start command
cmd.start()

//here if length of resChan is known it works else it keeps waiting for resChan
for {
  result <- resChan
  //do some operation on result
}

//wait for command
cmd.wait()

return result;

Also the resChan is not closed, there is only way to stop data collection that is when command execution stops.

CodePudding user response:

If I understood correctly you could listen to the results concurrently and collect them for later use, something like (Playground):

func main() {
    cmd := &command{
        ResChan: make(chan int),
        done:    make(chan struct{}),
    }
    collector := &collector{
        // We use the command's channel to get the values
        ch:   cmd.ResChan,
        done: make(chan struct{}),
    }

    collector.collect()
    cmd.start()
    cmd.wait()
    collector.stop()
    fmt.Println(collector.Results)
}

type collector struct {
    ch      chan int
    Results []int
    done    chan struct{}
}

func (c *collector) collect() {
    go func() {
        for {
            // The select will block until either of the channels receives a value
            // it will always execute one case at the time (sequential execution).
            // That's why we don't need to lock the slice to modify it
            select {
            case v := <-c.ch:
                c.Results = append(c.Results, v)
            case <-c.done:
                return
            }
        }
    }()
}

func (c *collector) stop() {
    // Send a signal into the channel to stop the collection of results
    c.done <- struct{}{}
}

type command struct {
    ResChan chan int
    done    chan struct{}
}

func (c *command) start() {
    go func() {
        // The command gets the results and sends them 
        // into the channel to be consumed by the user
        for i := 0; i < 10; i   {
            c.ResChan <- i
        }
        // Other executions take place and once they 
        // finish we send the signal to the wait command
        time.Sleep(time.Second)
        c.done <- struct{}{}
    }()
}

func (c *command) wait() {
    // Blocks until something is sent to the done channel
    <-c.done
}

collector.collect() and cmd.start() will be executing concurrently and sharing values by communicating through the ResChan channel. You don't need to know the results length.

CodePudding user response:

if you want chan can be done by time tick just like :

type msg struct {
}

func main() {
    // time tick : 10s
    t := time.NewTicker(time.Duration(5) * time.Second)
    ch := make(chan msg)
    select {
    case <-ch:
        // do something you want
    case <-t.C:
        // done
        fmt.Println(" have done by tick")
    }
    fmt.Println("end")
}

or if you want to have another channel to close

    ch := make(chan msg)
    doneCh := make(chan done)
    for {
        select {
        case <-ch:
            // do something you want
        case <-doneCh:
            // done
            fmt.Println(" have done by another channel")
            break
        }
    }
    fmt.Println("end")

or this

type msg struct {
    Done bool
    // and another msg you want
}

    ch := make(chan msg)
    for {
        msg := <-ch
        if msg.Done {
            break
        }
    }
    fmt.Println("end")

my English is not good, so I may have mistake for understandings or descriptions :)

CodePudding user response:

try this

    //start command
    cmd.start()

    //here if length of resChan is known it works else it keeps waiting for resChan
    for {
        select {
            case result :=<- resChan
                //your op here
        }
    }

    //wait for command
    cmd.wait()

    return result;
  •  Tags:  
  • go
  • Related