Go 使用上下文取消子进程的执行

Go 使用上下文取消子进程的执行,go,Go,我试图弄清楚如何在Go中使用上下文模式。 我模拟的情况是,由于执行超时,需要取消多个长时间运行的子goroutine。据我所知,上下文的主要用途之一是在I/O超时或用户在处理结束前离开页面时停止所有子进程 我的代码: package main import ( "context" "fmt" "time" ) func doIt(ctx context.Context, filename string) { // simulate not ending fil

我试图弄清楚如何在Go中使用上下文模式。 我模拟的情况是,由于执行超时,需要取消多个长时间运行的子goroutine。据我所知,上下文的主要用途之一是在I/O超时或用户在处理结束前离开页面时停止所有子进程

我的代码:

package main

import (
    "context"
    "fmt"
    "time"
)

func doIt(ctx context.Context, filename string) {
    // simulate not ending file processing - 
    // internals of this loop could not change 
    // e.g. it is call of some third party or stdlib function that hangs
    for {
        fmt.Printf("processing file %s\n", filename)
        time.Sleep(50 * time.Millisecond)
    }
}

func main() {
    startFileProcessing()
    fmt.Println("End of processing")
    time.Sleep(500 * time.Millisecond)
    fmt.Println("Do something else")

}

func startFileProcessing() {
    // set file processing timeout
    ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
    defer cancel()

    // start two parallel processes
    go doIt(ctx, "file1")
    go doIt(ctx, "file2")

    select {
    case <-ctx.Done():
        fmt.Println("file processing timeout")
        return
    }
}
我希望在“文件处理超时”之后不会看到“处理文件”行

如何修复它

编辑:@Mellow旱獭指出,环境本身并不能阻止孩子们外出,为此提出了解决方案。但是他的更改是在doIt函数中的循环中进行的,这并不能完全回答这个问题,因为在doIt函数中没有for循环,而是可能存在无法更改的第三方(或stdlib)函数调用

所以让我重新表述一下问题-

如何取消一些长时间运行的进程,以 没有访问权限-挂起时间超过超时时间


上下文本身不会停止子goroutine。在goroutine中运行的应用程序代码必须检查上下文,并在上下文完成时从goroutine返回。下面是一个如何检查上下文的示例:

func doIt(ctx context.Context, filename string) {
  // simulate not ending file processing
  for {
    fmt.Printf("processing file %s\n", filename)
    time.Sleep(50 * time.Millisecond)
    select {
    case <-ctx.Done():
        return
    default:
    }
  }
}
func doIt(ctx context.context,文件名字符串){
//模拟不结束文件处理
为了{
fmt.Printf(“正在处理文件%s\n”,文件名)
时间。睡眠(50*时间。毫秒)
挑选{

case上下文本身不会停止子goroutine。在goroutine中运行的应用程序代码必须检查上下文,并在上下文完成时从goroutine返回。下面是如何检查上下文的示例:

func doIt(ctx context.Context, filename string) {
  // simulate not ending file processing
  for {
    fmt.Printf("processing file %s\n", filename)
    time.Sleep(50 * time.Millisecond)
    select {
    case <-ctx.Done():
        return
    default:
    }
  }
}
func doIt(ctx context.context,文件名字符串){
//模拟不结束文件处理
为了{
fmt.Printf(“正在处理文件%s\n”,文件名)
时间。睡眠(50*时间。毫秒)
挑选{

谢谢。但第一个循环周期在线锁定"案例但是如何取消一些长时间运行的进程,这些进程的内部我没有访问权——比如说,替代函数doIt的是一些第三方或stdlib函数——它们的挂起时间超过超时时间。@sev3ryn除非在goroutine中执行的代码提供了一种机制,否则无法取消长时间运行的goroutine。t这里没有机制可以杀死在goroutine中执行的代码外部的goroutine。谢谢。但是第一个循环循环会锁定行"案例但是如何取消一些长时间运行的进程,这些进程的内部我没有访问权——比如说,替代函数doIt的是一些第三方或stdlib函数——它们的挂起时间超过超时时间。@sev3ryn除非在goroutine中执行的代码提供了一种机制,否则无法取消长时间运行的goroutine。t在goroutine中执行的代码外部没有杀死goroutine的机制。