从 Done 通道和未关闭通道的 GC 生成 context.Context

背景:

我正在利用自定义 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收集该通道,即使它从未关闭?


慕容708150
浏览 95回答 1
1回答

有只小跳蛙

您不需要关闭频道。如果没有任何内容引用该通道,它将被垃圾收集。您的频道逻辑看起来是正确的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go