Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang prevent channel from blocking

I am building a server that uses websockets.
Currently every connected client uses two goroutines. One for reading and one for writing. The writing goroutine basically listens to a channel for messages it should send and then tries to deliver them.

type User struct{
    send chan []byte
    ...
}

func (u *User) Send(msg []byte){
    u.send <- msg
}

Problem is, that a read from client A may cause a write to client B. Suppose the connection to B has some problems however (e.g. very slow) and it's send channel is already full. Current behaviour is, that trying to add a message to the channel now starts blocking, until something is removed from the channel. This means, that now A waits until B's buffer is no longer full.

I want to solve it somewhat like this:

func (u *User) Send(msg []byte) err{
    u.send, err <- msg
    if err != nil{
        //The channels buffer is full.
        //Writing currently not possible.
        //Needs appropriate error handling.
        return err
    }
    return nil
}

Basically instead of blocking I want error handling in case the buffer is full. How do I achieve that best?

like image 544
user2089648 Avatar asked Feb 20 '15 17:02

user2089648


People also ask

Does Golang channel block?

Channel operation (i.e. write or read) are blocking in nature. This means: When we send data into the channel using a GoRoutine, it will be blocked until the data is consumed by another GoRoutine. When we receive data from channel using a GoRoutine, it will be blocked until the data is available in the channel.

How do I create a non-blocking channel in Golang?

Go by Example: Non-Blocking Channel Operations However, we can use select with a default clause to implement non-blocking sends, receives, and even non-blocking multi-way select s. Here's a non-blocking receive. If a value is available on messages then select will take the <-messages case with that value.

Do I need to close Golang channel?

It's OK to leave a Go channel open forever and never close it. When the channel is no longer used, it will be garbage collected. Note that it is only necessary to close a channel if the receiver is looking for a close. Closing the channel is a control signal on the channel indicating that no more data follows.

Do buffered channels block Golang?

Golang provides buffered channels, which allow you to specify a fixed length of buffer capacity so one can send that number of data values at once. These channels are only blocked when the buffer is full. Likewise, the channel on the receiving end will only block when the buffer is empty.


1 Answers

As ThunderCat pointed out in his comment the solution is

func (u *User) Send(msg []byte){
    select{
    case u.send <- msg:
    default: //Error handling here
    }
}
like image 91
user2089648 Avatar answered Oct 19 '22 09:10

user2089648