取消使用上下文执行子流程

I'm trying to figure out how to work with context pattern in Go. I'm simulating the case when multiple long running child goroutines need to be cancelled because of timeout of their execution. As I understood one of the main usages of context is to stop all child processes in case of I/O timeout or if user left page before end of processing.

My code:

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
", 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
    }
}

Playground.

Which outputs:

processing file file2
processing file file1
processing file file1
processing file file2
processing file file1
file processing timeout
End of processing
processing file file2
processing file file2
processing file file1
processing file file1
processing file file2
Do something else

I expect not to see "processing file" lines after "file processing timeout".

How to fix it?

Edit: @Mellow Marmot pointed out that context does not stop child goroutines on its own and proposed solution for this. But his changes are within loop in doIt function what doesn't answer the question completely because instead of for loop in doIt function there could be some third party (or stdlib) function call that couldn't be changed.

So let me rephrase question -

How to cancel some long running processes to internals of which I don't have access - that hangs for more time than timeout?

The context does not stop child goroutines on its own. The application code running in the goroutines must check the context and return from the goroutine when the context is done. Here's an example of how to check the context:

func doIt(ctx context.Context, filename string) {
  // simulate not ending file processing
  for {
    fmt.Printf("processing file %s
", filename)
    time.Sleep(50 * time.Millisecond)
    select {
    case <-ctx.Done():
        return
    default:
    }
  }
}

playground example

It's not possible to to cancel a long running goroutine unless the code executing in the goroutine provides a mechanism to do so. There's no mechanism for killing a goroutine external to the code executing in the goroutine.