net / context的cancel()函数有什么作用?

时间:2015-08-23 01:41:11

标签: go

enter image description hereWithDeadline()WithTimeout()函数都返回cancel函数,文档说这些函数总是以延迟调用,例如:

func slowOperationWithTimeout(ctx context.Context) (Result, error) {
    ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
    defer cancel()  // releases resources if slowOperation completes before timeout elapses

但是这个功能实际上发布了什么“资源”?

1 个答案:

答案 0 :(得分:0)

您提供的代码示例来自the context.WithTimeout documentation,此处稍作修改:

func slowOperationWithTimeout(parentContxt context.Context) (Result, error) {
    childContext, cancel := context.WithTimeout(parentContxt, 100*time.Millisecond)
    defer cancel()  // releases resources if slowOperation completes before timeout elapses
    return slowOperation(childContext)
}

(此处我已重新命名为ctx,以明确我在谈论的内容,在实际代码中,最好只使用ctx,因为您不需要&# 39; t想要或需要区分父/子上下文。)

调用返回的取消函数(至少)做了两件重要的事情。 首先,它关闭childContext.Done()返回的频道。例如,如果slowOperation在具有该上下文(或[宏]子上下文)的goroutine中启动了某些内容,则可能会导入此内容。

其次,取消childContext会让parentContext忘记它。 在局部变量中有子上下文的引用,在其所有子项的父列表中有另一个引用(并且任何引用slowOperation可能保留)。如果在不再需要它时它没有被取消,那么父母会浪费空间来保持它,直到子环境最终超时并取消它自己,以及其他可能延迟子环境的事情,以及它。完成垃圾收集的渠道。

在取消之前,上下文实现(或未来的更改)也可以使用其他资源。 如果文档说你应该做某事,那就去做吧(即使它在当前的实现中什么都不做)。 从这个意义上讲,答案是"为什么?"对于这样的事情很简单,"因为文档说的是使用它的正确方法"。