登录
首页 >  Golang >  Go问答

如果上下文被取消,则终止函数执行

来源:Golang技术栈

时间:2023-03-21 10:44:27 217浏览 收藏

目前golang学习网上已经有很多关于Golang的文章了,自己在初次阅读这些文章中,也见识到了很多学习思路;那么本文《如果上下文被取消,则终止函数执行》,也希望能帮助到大家,如果阅读完后真的对你学习Golang有帮助,欢迎动动手指,评论留言并分享~

问题内容

我有这个最初不支持上下文的当前函数。

func (s *Service) ChunkUpload(r *multipart.Reader) error {
    chunk, err := s.parseChunk(r)
    if err != nil {
        return fmt.Errorf("failed parsing chunk %w", err)
    }

    if err := os.MkdirAll(chunk.UploadDir, 02750); err != nil {
        return err
    }

    if err := s.saveChunk(chunk); err != nil {
        return fmt.Errorf("failed saving chunk %w", err)
    }

    return nil
}

我已经更新了它的方法调用,现在将 acontext.Context作为它的第一个参数。我的主要目标是在上下文被取消后立即终止并返回函数。

我最初的实现是这样的。

func (s *Service) ChunkUpload(ctx context.Context, r *multipart.Reader) error {
    errCh := make(chan error)

    go func() {
        chunk, err := s.parseChunk(r)
        if err != nil {
            errCh 

然而,当我想到代码的执行时,我意识到这并没有达到我的目标。由于所有函数的逻辑都在一个单独的 go 例程中,即使上下文被取消并且我ChunkUpload提前返回,go 例程中的代码将继续执行,因此与原始代码没有真正的区别。

下一个虽然可以,只是将上下文传递给所有内部函数,例如s.parseChunks.saveChunk但是这个选项似乎也不正确,因为我需要在每个函数中实现取消。将这个原始函数重构为上下文感知并在上下文被取消后立即终止的正确方法是什么?

正确答案

函数调用和 goroutines 不能被调用者终止,函数和 goroutines 必须支持取消,通常通过context.Context值或done通道。

在任何一种情况下,函数都负责检查/监视上下文,如果请求取消(当上下文的完成通道关闭时),则提前返回。没有更简单/自动的方法。

如果任务在循环中执行代码,一个方便的解决方案是在每次迭代中检查完成的通道,如果它关闭则返回。如果任务是一个“整体”,则实现者负责使用/插入“检查点”,如果请求取消,则可以合理地提前中止任务。

检查 done 通道是否关闭的一种简单方法是使用 non-blocking select,例如:

select {
case 

当任务使用其他通道操作时必须小心,因为它们可能会以不确定的方式阻塞。这些选择也应该包括ctx.Done()频道:

select {
case v := 

还要小心,因为如果上面的 receive from someChannelnever 阻塞,则不能保证取消被正确处理,因为如果多个通信可以在 a 中进行select,则随机选择一个(并且不能保证永远选择)。在这种情况下,您可以结合上述 2:首先对取消进行非阻塞检查,然后将 aselect与您的通道操作 取消监控一起使用。

理论要掌握,实操不能落!以上关于《如果上下文被取消,则终止函数执行》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表