golang fifo缓冲频道

时间:2016-05-04 15:50:43

标签: go channel fifo

根据我的理解:当通道满时,GO中的缓冲通道不是FIFO 我在我的应用程序中需要这种行为(FIFO行为) 我怎样才能实现这种行为?那是否有任何开源?
提前致谢

编辑:
有些人不喜欢这个问题,所以让我更清楚一点:
我的意思是当缓冲的频道已满且多个发件人被阻止时 在尝试向频道添加项目时,他们将被释放的顺序 不是FIFO。您还可以阅读此讨论:https://github.com/golang/go/issues/11506

所以是的,我正在寻找实现这种行为的第三方图书馆 很抱歉不清楚。

2 个答案:

答案 0 :(得分:8)

Go中的缓冲通道始终为FIFO。规范明确指出:

  

频道充当先进先出队列。

如果来自通道的值不是FIFO,则这是通道实现中的错误。

以下代码应始终按正确的顺序打印1,2,3,4:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int, 3)
    ch <- 1
    ch <- 2
    ch <- 3

    go func() {
        ch <- 4
    }()

    time.Sleep(time.Second)

    for i := 0; i < 4; i++ {
        fmt.Println(<-ch)
    }
}

Playground link

请注意,当有多个并发发件人时,没有担保人会先发送哪个值。如果有多个等待发送者,并且有人从通道缓冲区中删除了一个元素(或者在无缓冲通道的情况下,尝试从通道接收),运行时将随机选择一个发送goroutines。

示例:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int, 2)
    ch <- 1

    go func() {
        ch <- 2
    }()

    go func() {
        ch <- 3
    }()

    time.Sleep(time.Second)

    for i := 0; i < 3; i++ {
        fmt.Println(<-ch)
    }
}

Playground link

如果您多次运行此代码,您可以看到输出有时会是1,2,3或1,3,2。(这在操场上不起作用,因为输出被缓存)< / p>

答案 1 :(得分:1)

您可以使用链接列表。

容器/列表包(https://golang.org/pkg/container/)实现了一个双向链接列表,该列表可用作队列。也许,它还实现了堆,该堆允许您创建具有优先级的队列。无论如何,最简单的方法是链接列表IHMO:

queue := list.New()

queue.PushBack("Hello ") // Enqueue
queue.PushBack("world!")

for queue.Len() > 0 {
    e := queue.Front() // First element
    fmt.Print(e.Value)

    queue.Remove(e) // Dequeue
}