update Added a deadline
Channels are great because you can easily rewire them from fifos into multiplexers , funnels and fan-outs.
In this case we want to implement a priority fifo-- the P could be a TTL or value indicator.
Not much is needed, just a custom sort.Interface
impl. based on your ordering field P
--for priority. Then just read inChan
into the buf, sort , and write to outChan
package main
import (
"fmt"
"math/rand"
"sort"
"time"
"strconv"
"context"
)
type PriorityStruct struct {
P int
name string
}
const BUFSIZE = 10
type PriorityChan chan PriorityStruct
type PriorityBuf []PriorityStruct
func (s PriorityBuf) Len() int {
return len(s)
}
func (s PriorityBuf) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s PriorityBuf) Less(i, j int) bool {
return s[i].P < s[j].P
}
func Sender(pchan PriorityChan) {
for {
randNum := rand.Intn(3)
pchan <- PriorityStruct{
P: randNum,
name: "Bob-" + strconv.Itoa(randNum),
}
time.Sleep(10 * time.Millisecond)
}
}
func Prioritize(ctx context.Context, inChan PriorityChan, outChan PriorityChan) {
for {
buf := make(PriorityBuf, BUFSIZE)
var i int
for i = range buf {
select{
case buf[i] = <-inChan:
case <-ctx.Done():
break
}
buf[i] = <-inChan
}
sort.Sort(buf)
for j:= 0; j <= i; j++ {
outChan <- buf[j]
}
}
}
func Receiver(rchan PriorityChan) {
for {
fmt.Printf("%v\n", <-rchan)
}
}
func main() {
inChan := make(PriorityChan)
outChan := make(PriorityChan)
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(50 * time.Millisecond))
defer cancel()
go Sender(inChan)
go Receiver(outChan)
go Prioritize(ctx, inChan, outChan)
<- time.After(5 * time.Second)
}
Run it
go run priority-channel.go |head -n 15
{0 Bob-0}
{0 Bob-0}
{0 Bob-0}
{1 Bob-1}
{1 Bob-1}
{1 Bob-1}
{2 Bob-2}
{2 Bob-2}
{2 Bob-2}
{2 Bob-2}
{0 Bob-0}
{0 Bob-0}
{1 Bob-1}
{1 Bob-1}
{2 Bob-2}
Check it out: https://play.golang.org/p/wWgi5rPcIwb
If you're not on go-nuts -- it's a good community of go-users .
Top comments (0)