Golang如何防止通道阻塞

huangapple go评论81阅读模式
英文:

Golang prevent channel from blocking

问题

我正在构建一个使用Websockets的服务器。目前,每个连接的客户端都使用两个goroutine,一个用于读取,一个用于写入。
写入的goroutine基本上会监听一个通道,以获取应该发送的消息,然后尝试将它们传递给客户端。

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

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

问题是,从客户端A读取可能会导致向客户端B写入。
然而,假设与B的连接存在一些问题(例如,非常慢),并且它的发送通道已经满了。当前的行为是,尝试向通道添加消息会导致阻塞,直到有东西从通道中移除。
这意味着现在A要等到B的缓冲区不再满。

我想要这样解决:

func (u *User) Send(msg []byte) error{
    select {
    case u.send <- msg:
        return nil
    default:
        // 通道的缓冲区已满。
        // 当前无法写入。
        // 需要适当的错误处理。
        return fmt.Errorf("channel buffer is full")
    }
}

基本上,我希望在缓冲区已满时进行错误处理,而不是阻塞。如何最好地实现这一点?

英文:

I am building a server that uses websockets.<br>
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 &lt;- 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 &lt;- 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?

答案1

得分: 6

如ThunderCat在他的评论中指出的那样,解决方案是:

func (u *User) Send(msg []byte){
    select{
    case u.send <- msg:
    default: //在这里处理错误
    }
}
英文:

As ThunderCat pointed out in his comment the solution is

func (u *User) Send(msg []byte){
    select{
    case u.send &lt;- msg:
    default: //Error handling here
    }
}

huangapple
  • 本文由 发表于 2015年2月21日 01:15:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/28634576.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定