停止goroutine中的所有递归函数

mas*_*oud 4 go goroutine

盯着运行递归函数的goroutine,我想发送一个信号来阻止那些递归函数.这是功能(功能并不重要):

func RecursiveFunc(x int, depth int, quit chan bool) int {

    if depth == 0 {
        return 1
    }

    if quit != nil {
        select {
        case <-quit:
            return 0
        default:
        }
    }

    total := 0

    for i := 0; i < x; i++ {

        y := RecursiveFunc(x, depth - 1, quit)

        if y > 0 {
            total += y
        }

    }

    return total
}
Run Code Online (Sandbox Code Playgroud)

此功能可能需要很长时间才能完成,我想在发送退出信号并使用结果(无论是什么)后停止它.要运行它:

import (
    "fmt"
    "time"
    "sync"
)

func main() {

    quit := make(chan bool)
    wg := &sync.WaitGroup{}
    result := -1

    go func() {
        defer wg.Done()
        wg.Add(1)
        result = RecursiveFunc(5, 20, quit)
    }()

    time.Sleep(10 * time.Millisecond)

    close(quit) // Using `quit <- true` doesn't work

    wg.Wait()

    fmt.Println(result)
}
Run Code Online (Sandbox Code Playgroud)

为了停止goroutine,我正在使用一个频道说quit,关闭它后,程序运行良好,但我不想真正关闭频道,我只想发送一个信号quit <- true.但是,quit <- true不起作用,我可能只退出一个递归实例.

如何通过发送退出信号来停止所有递归函数实例?

小智 6

您可以使用上下文执行您要执行的操作.

您可以将一个context.Context对象作为第一个参数传递给您需要从外部停止的函数,并调用相应的cancel函数向该函数发送"取消信号",这将导致该Done()通道context.Context被关闭,并且被调用因此,将在select声明中向功能通知取消信号.

以下是该函数如何处理取消信号context.Context:

func RecursiveFunc(ctx context.Context, x int, depth int) int {

    if depth == 0 {
        return 1
    }

    select {
    case <-ctx.Done():
        return 0
    default:
    }

    total := 0

    for i := 0; i < x; i++ {

        y := RecursiveFunc(ctx, x, depth-1)

        if y > 0 {
            total += y
        }

    }

    return total
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用新签名调用该函数:

func main() {

    wg := &sync.WaitGroup{}
    result := -1

    ctx, cancel := context.WithCancel(context.Background())

    go func() {
        defer wg.Done()
        wg.Add(1)
        result = RecursiveFunc(ctx, 5, 20)
    }()

    time.Sleep(10 * time.Millisecond)

    cancel()

    wg.Wait()

    fmt.Println(result)
}
Run Code Online (Sandbox Code Playgroud)