在 golang 中处理 SIGINT (ctrl-c) 将其转换为恐慌

问题描述 投票:0回答:1

我的目标是拥有一个 SIGINT 处理程序(即 CLI 上的 Ctrl-C),它将允许延迟函数调用运行,而不是导致硬退出。其用例是在一个具有非常长时间运行的测试的测试套件中,我希望 CLI 用户能够根据需要使用 Ctrl-C 尽早触发测试清理。测试清理函数应该全部位于每个测试函数的延迟函数堆栈上,因此在我看来,将 SIGINT 降级为恐慌应该会导致这些清理函数运行。

下面的代码是我尝试这样做的。如果你用

go run .
运行它,你会看到

$ go run .
regular action ran!
post-Sleep action ran!
deferred action ran!

但是如果你在 5 秒睡眠期间中断它,你会看到这个:

regular action ran!^Cpanic: interrupt

goroutine 8 [running]:
main.panic_on_interrupt(0xc00007c180)
        /home/curran/dev/test/main.go:12 +0x5e
created by main.main
        /home/curran/dev/test/main.go:20 +0xab
exit status 2

我添加了中断处理程序和 goroutine,因为我认为这会将 SIGINT 降级为恐慌,并允许对

fmt.Printf("deferred action ran!")
的调用执行。然而,事实并非如此。

这是有问题的代码:

package main

import (
        "fmt"
        "time"
        "os"
        "os/signal"
)

func panic_on_interrupt(c chan os.Signal) {
        sig := <-c
        panic(sig)
}

func main() {
        c := make(chan os.Signal, 1)
        // Passing no signals to Notify means that
        // all signals will be sent to the channel.
        signal.Notify(c, os.Interrupt)
        go panic_on_interrupt(c)

        fmt.Printf("regular action ran!")
        defer fmt.Printf("deferred action ran!")
        time.Sleep(5 * time.Second)
        fmt.Printf("post-Sleep action ran!")
}                                                                                                                                                                                                                                             
linux go goroutine sigint defer-keyword
1个回答
0
投票
func main() {
    fmt.Printf("regular action ran!")
    defer fmt.Printf("deferred action ran!")

    go startLongRunningTest()
    defer longRunningTestCleanupCode()

    //time.Sleep(5 * time.Second)
    //fmt.Printf("post-Sleep action ran!")

    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt)
    <-c
}                                                                                                                                                                                                                                             

time.Sleep()
阻止 goroutine 运行指定的时间。
您可以
defer()
清理代码。
此外,您可以在单独的 goroutine 中运行耗时的测试,而不是在那里恐慌。
如果可能,请避免使用
panic()

© www.soinside.com 2019 - 2024. All rights reserved.