Polling a simple queue from within another, and filling the first queue from the second queue

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

Polling a simple queue from within another, and filling the first queue from the second queue

问题

换句话说,事件驱动队列的流程如下:

  • 轮询事件队列
  • 如果找到事件,则处理事件,然后进行下一次轮询
  • 如果未找到事件,则轮询数据队列
  • 如果找到数据,则将其推送到事件队列,并开始下一次轮询事件队列
  • 如果未找到数据,则退出流程

以下是代码:

package main

import "fmt"

type Queue struct {
	stream []string
}

// Next 从流中返回第一个元素。
// 如果流中没有元素,则返回 false。
func (q *Queue) Next() (s string, ok bool) {
	if len(q.stream) == 0 {
		return s, false
	}
	s = q.stream[0]
	q.stream = q.stream[1:]
	return s, true
}

func main() {
	// 定义队列
	events := []string{"event"}
	q1 := &Queue{stream: events}
	data := []string{"data1", "data2", "data3"}
	q2 := &Queue{stream: data}

	// 轮询第一个队列
	for e, ok := q1.Next(); ok; e, ok = q1.Next() {
		// q1 中没有内容
		if !ok {
			fmt.Println("在 q1 中未找到任何内容")

			// 轮询第二个队列
			d, ok := q2.Next()
			if !ok {
				return
			}

			// 在 q2 中找到 d 并添加到 q1
			fmt.Printf("在 q2 中找到:%v\n", d)
			q1.stream = append(q1.stream, d)
			return
		}

		// 对 e 进行一些操作...
		fmt.Printf("在 q1 中找到:%v %v\n", e, ok)
	}
}

在这段代码中,我只得到了第一个队列中的元素:

在 q1 中找到:event true

代码从未轮询第二个队列并将其元素添加到第一个队列中。我做错了什么?

如果我尝试:

// 轮询第一个队列
for e, ok := q1.Next() {
	// ...
}

编译器会报错:

tmp/sandbox299553905/main.go:28:25: 语法错误:e, ok := q1.Next() 用作值

请给予一些建议,谢谢。


更新: 这里是循环的解决方案。

// 轮询第一个队列
for e, ok := q1.Next(); true; e, ok = q1.Next() {
	// q1 中没有内容
	if !ok {
		fmt.Println("在 q1 中未找到任何内容")

		// 轮询第二个队列
		for d, ok := q2.Next(); true; d, ok = q2.Next() {
			if !ok {
				fmt.Println("在 q2 中未找到任何内容。退出")
				return
			}

			// 在 q2 中找到 d 并添加到 q1
			fmt.Printf("在 q2 中找到:%v。添加到 q1\n", d)
			q1.stream = append(q1.stream, d)
			break
		}
		continue
	}

	// 对 e 进行一些操作...
	fmt.Printf("在 q1 中找到:%v。进行操作\n", e)
}

你可以在 playground 中测试它:https://play.golang.org/p/qo0zoBPROe

英文:

In other words, the flow of an event-driven queue:

  • poll event queue
  • if event found, process event, then next poll cycle
  • if no event found, poll data queue
  • if data found, push to event queue, start next cycle polling event queue
  • if no data found, exit flow

Here is the code:

package main

import "fmt"

type Queue struct {
	stream []string
}

// Next returns first element from stream.
// Returns false if no element is in the stream.
func (q *Queue) Next() (s string, ok bool) {
	if len(q.stream) == 0 {
		return s, false
	}
	s = q.stream[0]
	q.stream = q.stream[1:]
	return s, true
}

func main() {
	// define queues
	events := []string{"event"}
	q1 := &Queue{stream: events}
	data := []string{"data1", "data2", "data3"}
	q2 := &Queue{stream: data}

	// poll first queue
	for e, ok := q1.Next(); ok; e, ok = q1.Next() {
		// nothing in q1
		if !ok {
			fmt.Println("Nothing found in q1")

			// poll second queue
			d, ok := q2.Next()
			if !ok {
				return
			}

			// found d in q2 and append to q1
			fmt.Printf("found in q2 %v\n", d)
			q1.stream = append(q1.stream, d)
			return
		}

		// do some stuff to e ...
		fmt.Printf("found in q1 %v %v\n", e, ok)
	}
}

Try it in the playground https://play.golang.org/p/bgJzq2hCfl.

All I get is the element in the first queue.

found in q1 event true

The code never polls the second queue and append its elements to the first queue. What do i wrong?

If I try

// poll first queue
for e, ok := q1.Next() {
	// ...
}

the compiler throws

tmp/sandbox299553905/main.go:28:25: syntax error: e, ok := q1.Next() used as value

Any hints appreciated.


Update: Here is the solution to the loop.

// poll first queue
for e, ok := q1.Next(); true; e, ok = q1.Next() {
	// nothing in q1
	if !ok {
		fmt.Println("Nothing found in q1")

		// poll second queue
		for d, ok := q2.Next(); true; d, ok = q2.Next() {
			if !ok {
				fmt.Println("Nothing found in q2. exit")
				return
			}

			// found d in q2 and append to q1
			fmt.Printf("found in q2: %v. append to q1\n", d)
			q1.stream = append(q1.stream, d)
			break
		}
		continue
	}

	// do some stuff to e ...
	fmt.Printf("found in q1: %v. do stuff\n", e)
}

You can test it in the playground https://play.golang.org/p/qo0zoBPROe.

答案1

得分: 2

当它找不到任何内容时,你退出循环。只需将你的for循环更改为以下形式,但请注意,这将使循环无限进行,所以你必须使用breakreturn来跳出循环。

for e, ok := q1.Next(); ok || !ok ; e, ok = q1.Next() {
英文:

You exit the loop when it doesn't find anything. Just change your for loop to the following, but note that this makes the loop infinite, so you have to break out or return to get out.

for e, ok := q1.Next(); ok || !ok ; e, ok = q1.Next() {

答案2

得分: 2

在第一次迭代之后,“increment”发生,这次将ok设置为false。下一步比较ok == true(循环终止条件),这不成立,因此退出。

现在,如果我正确理解你的意图,我会修改循环为:

// 首先轮询第一个队列
for e, ok := q1.Next(); true; e, ok = q1.Next() {
// q1中没有内容
if !ok {
fmt.Println("在q1中未找到任何内容")

    // 轮询第二个队列
    d, do := q2.Next()
    if !do {
        break
    }

    // 在q2中找到d并添加到q1
    fmt.Printf("在q2中找到 %v\n", d)
    q1.stream = append(q1.stream, d)
} else {

    // 对e进行一些操作...
    fmt.Printf("在q1中找到 '%v' ok=%v\n", e, ok)
}

}

英文:

After the first iteration, the "increment" happens and this time ok is set to false. The next step compares ok == true (loop termination condition) which is not the case and thus exits.

Now, if I understand correctly what you try to do, I would modify the loop to:

// poll first queue
for e, ok := q1.Next(); true; e, ok = q1.Next() {
	// nothing in q1
	if !ok {
		fmt.Println("Nothing found in q1")

		// poll second queue
		d, do := q2.Next()
		if !do {
			break
		}

		// found d in q2 and append to q1
		fmt.Printf("found in q2 %v\n", d)
		q1.stream = append(q1.stream, d)
	} else {

		// do some stuff to e ...
		fmt.Printf("found in q1 '%v' ok=%v\n", e, ok)
	}
}

huangapple
  • 本文由 发表于 2017年9月1日 03:54:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/45989127.html
匿名

发表评论

匿名网友

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

确定