从完成通道和未关闭通道的 GC 中生成 context.Context
generate context.Context from Done channel & GC of unclosed channels
背景:
我正在利用自定义 LDAP 服务器 package. It uses a Done
channel within requests to let the handler know if - say the client disconnects - and thus the handler should abort also. For example。
由于 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
会收集这个频道吗,即使它从未关闭过?
您不需要关闭频道。如果没有任何内容引用频道,它将被垃圾收集。
您的频道逻辑似乎是正确的。
背景:
我正在利用自定义 LDAP 服务器 package. It uses a Done
channel within requests to let the handler know if - say the client disconnects - and thus the handler should abort also. For example。
由于 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
会收集这个频道吗,即使它从未关闭过?
- 即
您不需要关闭频道。如果没有任何内容引用频道,它将被垃圾收集。
您的频道逻辑似乎是正确的。