在Golang中,当等待命令执行完成时,从通道中收集数据。

huangapple go评论93阅读模式
英文:

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 &lt;- 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 := &amp;command{
		ResChan: make(chan int),
		done:    make(chan struct{}),
	}
	collector := &amp;collector{
        // We use the command&#39;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&#39;s why we don&#39;t need to lock the slice to modify it
			select {
			case v := &lt;-c.ch:
				c.Results = append(c.Results, v)
			case &lt;-c.done:
				return
			}
		}
	}()
}

func (c *collector) stop() {
	// Send a signal into the channel to stop the collection of results
	c.done &lt;- 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 &lt; 10; i++ {
			c.ResChan &lt;- i
		}
		// Other executions take place and once they 
        // finish we send the signal to the wait command
		time.Sleep(time.Second)
		c.done &lt;- struct{}{}
	}()
}

func (c *command) wait() {
	// Blocks until something is sent to the done channel
	&lt;-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 &lt;-ch:
		// do something you want
	case &lt;-t.C:
		// done
		fmt.Println(&quot; have done by tick&quot;)
	}
	fmt.Println(&quot;end&quot;)
}

or if you want to have another channel to close

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

or this

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

	ch := make(chan msg)
	for {
		msg := &lt;-ch
		if msg.Done {
			break
		}
	}
	fmt.Println(&quot;end&quot;)

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 :=&lt;- resChan
//your op here
}
}
//wait for command
cmd.wait()
return result;

huangapple
  • 本文由 发表于 2022年8月11日 09:16:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/73314282.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定