为什么 net/rpc/client 的 Go 方法需要缓冲通道?
Why does net/rpc/client's Go method require a buffered channel?
我无法弄清楚为什么该方法要求您专门提供一个缓冲通道。
func (*Client) Go
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call
Go invokes the function asynchronously. It returns the Call structure
representing the invocation. The done channel will signal when the
call is complete by returning the same Call object. If done is nil, Go
will allocate a new channel. If non-nil, done must be buffered or Go
will deliberately crash.
LeGEC 在评论中提到了这一点。
进一步挖掘,您会在 client.go
中找到这一点
func (call *Call) done() {
select {
case call.Done <- call:
// ok
default:
// We don't want to block here. It is the caller's responsibility to make
// sure the channel has enough buffer space. See comment in Go().
if debugLog {
log.Println("rpc: discarding Call reply due to insufficient Done chan capacity")
}
}
}
从此处可以看出,库希望调用完全异步。这意味着 done 通道必须有足够的容量来完全解耦两个进程(即完全没有阻塞)。
此外,当使用 select 语句时,它是执行 non-blocking 通道操作的惯用方法。
我无法弄清楚为什么该方法要求您专门提供一个缓冲通道。
func (*Client) Go
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call
Go invokes the function asynchronously. It returns the Call structure representing the invocation. The done channel will signal when the call is complete by returning the same Call object. If done is nil, Go will allocate a new channel. If non-nil, done must be buffered or Go will deliberately crash.
LeGEC 在评论中提到了这一点。
进一步挖掘,您会在 client.go
中找到这一点func (call *Call) done() {
select {
case call.Done <- call:
// ok
default:
// We don't want to block here. It is the caller's responsibility to make
// sure the channel has enough buffer space. See comment in Go().
if debugLog {
log.Println("rpc: discarding Call reply due to insufficient Done chan capacity")
}
}
}
从此处可以看出,库希望调用完全异步。这意味着 done 通道必须有足够的容量来完全解耦两个进程(即完全没有阻塞)。
此外,当使用 select 语句时,它是执行 non-blocking 通道操作的惯用方法。