登录
首页 >  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删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>