I am writing data to network.
The writing goroutine is like this.
forend:
for{
select{
case buf,ok:=<-sendqueue:
if !ok{
break forend
}
writeBuffer(conn,buf)
}
}
The variable conn is a net.Conn.
Then I want to use bufio to replace net.Conn.
iowriter:=bufio.NewWriter(conn)
iowriter will cache the data.To reduce the delay,I must flush the iowriter immediately when there is no more data in sendqueue.
So I add a default case to the writing goroutine
forend:
for{
select{
case buf,ok:=<-sendqueue:
if !ok{
break forend
}
writeBuffer(iowriter,buf)
default:
iowriter.Flush()
time.Sleep(time.Millisecond)
}
}
The time.Sleep is necessary,otherwise the goroutine will run busy loop.
But in this case, the really demand is to block not to sleep.
Finally, I found a solution,with two selects.
forend:
for{
select{
case buf,ok:=<-sendqueue:
if !ok{
break forend
}
writeBuffer(iowriter,buf)
}
nextloop:
for{
select{
case buf,ok:=<-sendqueue:
if !ok{
break forend
}
writeBuffer(iowriter,buf)
default:
iowriter.Flush()
break nextloop
}
}
}
But this solution is complicate.The second select is the duplicate of the first with a default case.Is there any better solution?
~~~~~~~~~~~~~~~~~~~~~~~ More explanation
The behavior here is like this.If the sendqueue is not empty,I continue to pop data and send it.If the sendqueue is empty,I want to flush the data cached in iowriter immediately and then waiting on the sendqueue again.
This behavior can be abstract like this.I want to do something when channel is empty,and then waiting on channel again,with blocking.I found the two duplicate select solution.But that solution may become more complicated when waiting on more than one channel.So I am looking for a better solution.