背景:
我正在利用自定义 LDAP 服务器包。它使用Done
请求中的通道让处理程序知道是否(例如客户端断开连接),因此处理程序也应该中止。
由于Done
通道是处理取消的旧方法 - 并且我希望支持取消链接 - 我context.Context
从这个通道创建了一个,如下所示:
func doneContext(p context.Context, done <-chan bool) (
ctx context.Context, cancel context.CancelFunc,
) {
ctx, cancel = context.WithCancel(p)
go func() {
<-done
cancel() // done closed, so cancel our context
}()
return
}
这假设done
通道将关闭:
客户端断开连接;和
成功的处理程序(完全运行完成)
第一个事实证明是正确的,而第二个事实则不然。成功的处理程序调用不会触发通道done
关闭 - 因此我泄漏了 go-routines。
为了解决这个问题 - 由于我context.Context
在处理程序完成时取消了自己的操作 - 成功与否,例如
// convert the client request's Done channel into a context.Context
ctx, cancel := doneContext(context.Background(), m.Done)
defer cancel() // clean-up context: rain or shine
我doneContext像这样更新了 go 例程:
go func() {
select {
case <-done:
cancel() // done closed, so cancel our context (like before)
case <-ctx.Done():
// when our context is canceled, recover the go-routine (even if done never closes)
}
}()
问题:
这是将旧式done
频道升级为更现代频道的正确方法吗context.Context
我应该担心我正在使用的外部包没有关闭通道吗done
?
即会GC
收集该通道,即使它从未关闭?
有只小跳蛙
相关分类