英文:
collect data from channel while waiting for command to complete its execution in golang
问题
我正在启动一个命令执行,触发一个服务,该服务会在一个通道(resChan)上发送结果。现在我需要收集在命令执行期间在这个通道上接收到的结果,但我不知道有多少数据对象会到达resChan。
//启动命令
cmd.start()
//如果知道resChan的长度,可以正常工作,否则会一直等待resChan
for {
result <- resChan
//对结果进行一些操作
}
//等待命令执行完成
cmd.wait()
return result;
另外,resChan没有被关闭,唯一停止数据收集的方法是当命令执行停止时。
英文:
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.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
//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;
<!-- end snippet -->
Also the resChan is not closed, there is only way to stop data collection that is when command execution stops.
答案1
得分: 1
如果我理解正确,你可以同时监听结果并将其收集以供以后使用,类似于(Playground):
func main() {
cmd := &command{
ResChan: make(chan int),
done: make(chan struct{}),
}
collector := &collector{
// 我们使用命令的通道来获取值
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 {
// select 语句将阻塞,直到其中任一通道接收到值
// 它每次只执行一个 case(顺序执行)
// 这就是为什么我们不需要锁定切片来修改它
select {
case v := <-c.ch:
c.Results = append(c.Results, v)
case <-c.done:
return
}
}
}()
}
func (c *collector) stop() {
// 向通道发送信号以停止结果的收集
c.done <- struct{}{}
}
type command struct {
ResChan chan int
done chan struct{}
}
func (c *command) start() {
go func() {
// 命令获取结果并将其发送到通道,供用户使用
for i := 0; i < 10; i++ {
c.ResChan <- i
}
// 其他执行过程完成后,我们发送信号给等待命令
time.Sleep(time.Second)
c.done <- struct{}{}
}()
}
func (c *command) wait() {
// 阻塞,直到有东西发送到 done 通道
<-c.done
}
collector.collect()
和 cmd.start()
将并发执行并通过 ResChan
通道进行值的传递。你不需要知道结果的长度。
英文:
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.
答案2
得分: 0
如果你想要通过时间间隔来完成任务,可以像这样做:
type msg struct {
}
func main() {
// 时间间隔:10秒
t := time.NewTicker(time.Duration(5) * time.Second)
ch := make(chan msg)
select {
case <-ch:
// 做你想做的事情
case <-t.C:
// 完成
fmt.Println("通过时间间隔完成")
}
fmt.Println("结束")
}
或者,如果你想要使用另一个通道来关闭:
ch := make(chan msg)
doneCh := make(chan done)
for {
select {
case <-ch:
// 做你想做的事情
case <-doneCh:
// 完成
fmt.Println("通过另一个通道完成")
break
}
}
fmt.Println("结束")
或者这样:
type msg struct {
Done bool
// 和其他你想要的消息
}
ch := make(chan msg)
for {
msg := <-ch
if msg.Done {
break
}
}
fmt.Println("结束")
我的英文不太好,所以我可能会在理解或描述方面有错误:)
英文:
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 :)
答案3
得分: -1
请尝试以下代码:
//开始命令
cmd.start()
//如果resChan的长度已知,则可以正常工作;否则,它将一直等待resChan
for {
select {
case result := <-resChan:
//在这里执行你的操作
}
}
//等待命令完成
cmd.wait()
return result;
希望对你有帮助!
英文:
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;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论