登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  Golang >  Go问答

Go语言:使用副本作为背景的上下文

来源:stackoverflow

时间:2024-03-09 21:54:26 167浏览 收藏

哈喽!大家好,很高兴又见面了,我是golang学习网的一名作者,今天由我给大家带来一篇《Go语言:使用副本作为背景的上下文》,本文主要会讲到等等知识点,希望大家一起学习进步,也欢迎大家关注、点赞、收藏、转发! 下面就一起来看看吧!

问题内容

相关但不相同:golang:如何在不派生的情况下复制 context 对象

从 context.background() 派生 context.withtimeout 并使子项可取消是否可以接受?我们目前有这个:

ctx = context.Background()
...
newCtx, cancelFunc = context.WithTimeout(ctx, someDuration)
...
os.exec.CommandContext(newCtx, myCmd).Run()
# via a signal handler: cancelFunc() // myCmd does not stop!!

也就是说,我们从后台上下文中派生出一个 withtimeout 上下文,然后在该上下文中使用 os.exec 执行命令,但是当我们调用 cancelfunc 时,cmd 并没有死亡。我想知道这是否与“副本”的确切措辞有关。来自:https://golang.org/pkg/context/

withtimeout 返回 withdeadline(parent, time.now().add(timeout))。

withdeadline 返回父上下文的副本,并将截止日期调整为不晚于 d。如果父级的截止日期已经早于 d,则 withdeadline(parent, d) 在语义上等同于parent。当截止时间到期、调用返回的取消函数时或当父上下文的 done 通道关闭时(以先发生者为准),返回的上下文的 done 通道将关闭。

所以问题是,如果您想取消复制,后台是否是“复制”的安全上下文?


解决方案


是的,像这样使用 context.background() 就可以了。

您的问题是 commandcontext.run() 在返回之前等待命令完成,因此您的 cancelfunc 永远无法取消命令的执行。您需要在 goroutine 中运行该命令(并在该 goroutine 终止时同步您的代码),然后您就可以有效地调用 cancelfunc 。

这是一个完整的工作示例(使用 unix 命令 yes,这意味着如果您使用的操作系统没有 yes 命令,则必须对其进行调整)。

package main

import (
    "context"
    "fmt"
    "os"
    "os/exec"
    "sync"
    "time"
)

func main() {
    ctx := context.Background()
    nctx, cancf := context.WithTimeout(ctx, 1000*time.Second)

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        cmd := exec.CommandContext(nctx, "yes", "I am running")
        cmd.Stdout = os.Stdout
        cmd.Run()
        fmt.Println("command done!")
    }()
    time.Sleep(time.Second / 100)
    cancf()

    wg.Wait()
}

请注意,即使命令在休眠 10 毫秒后被取消,这也会产生大量输出。

到这里,我们也就讲完了《Go语言:使用副本作为背景的上下文》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

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