简体   繁体   中英

golang fifo buffered channel

from my understanding: buffered channels in GO are not FIFO when the channel is full.
I need this behaviour in my application (FIFO behaviour).
How can I achieve that behaviour? Is there any open source for that?
Thanks in advance

EDIT:
some people disliked the question so let me be more clear:
I meant that when a buffered channel is full and multiple senders are blocked
while trying to add items to the channel the order in which they'll be released
is not FIFO. You can also read this discussion: https://github.com/golang/go/issues/11506

So yeah, I was looking for a third party library that implements that behaviour.
Sorry for not being clear.

Buffered channels in Go are always FIFO. The specification clearly says:

Channels act as first-in-first-out queues.

If the values coming out of the channel are not FIFO, then this is a bug in the channel implementation.

The following code should always print 1, 2, 3, 4 in this correct order:

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

Please note, that there is no guaruantee which value will be send first when there are multiple concurrent senders. If there are multiple waiting senders and someone removes one element from the channel buffer (or in the case of an unbuffered channel, tries to receive from the channel) the runtime will randomly choose one of the sending goroutines.

Example:

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

If you run this code multiple times, you can see that the output will sometimes either be 1, 2, 3 or 1, 3, 2. (This doesn't work on the playground, as the output is cached)

You could make use of Linked List.

The container/list package ( https://golang.org/pkg/container/ ) implements a doubly linked list which can be used as a queue. Perhaps, it also implements Heap which allows you to create queues with priority. Anyhow, the simplest way is Linked List 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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM