Search code examples
gogoroutine

How to close a goroutine which runs the flow based logics?


I have some goroutine logics like this:

go func() {
    do_things_0()
    do_things_1()
    do_things_2()
    do_things_3()
    ...
    ...
} ()

When the service receives a request, it will create such goroutine. And the goroutine maybe memory consuming and needs to run more than 30 minutes.

Sometimes, the service may notice the lack of memory, and needs to terminate some goroutines.

My questions are:

  1. How can I terminate the goroutine in the above example?
  2. Is there any way to know the used memory of each goroutine?

Update

  1. I read other SO answers that goroutine can't be killed outside
  2. I suppose that send a signal to the channel handled by the goroutine to make the goroutine quit is only suitable for the for loop based logics.
  3. I am looking for some best practice to close the goroutine for the flow based logics.

Solution

  • You should be able to adapt this easily to a for loop if you range over a list of the functions that are your steps:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func a() { fmt.Printf("a") }
    func b() { fmt.Printf("b") }
    func c() { fmt.Printf("c") }
    func d() { fmt.Printf("d") }
    func e() { fmt.Printf("e") }
    
    func f(quit <-chan struct{}) {
        for i := 0; i < 10000; i++ {
            for _, fn := range []func(){a, b, c, d, e} {
                select {
                case _, _ = <-quit:
                    fmt.Println("quit f")
                    return
                default:
                    fn()
                    time.Sleep(1 * time.Millisecond)
                }
            }
        }
    }
    
    func main() {
        quit := make(chan struct{})
        fmt.Println("go f")
        go f(quit)
        fmt.Println("sleep")
        time.Sleep(100 * time.Millisecond)
        fmt.Println("\nquit")
        close(quit)
        time.Sleep(10 * time.Millisecond)
        fmt.Println("exit")
    }
    

    Try it on the playground.

    The outer loop is just there to repeat the steps for long enough that we can witness the quit command happening.