在忽略 CTRL-C 的同时读取用户的输入

我想在 go 中读取用户输入并忽略用户通过捕获来终止我的进程的尝试CTRL-C.我旋转一个 goroutine 来捕获CTRL-C并写入通道。在这个阶段,我希望控制权返回到case <-intr主 goroutine 中,但这并没有发生。


这是运行的输出:


$ go run read.go 

Enter text: hello

Entered:hello


$go run read.go 

Enter text: ^CGot signal interrupt

Exiting signal handler..


Invalid input2

Interrupted.. Continuing

Enter text: ^C

Invalid input2

Enter text: ^C

Invalid input2

Enter text: ^C^C^C^C

Invalid input2

Enter text: ^C

Invalid input2

Enter text: ^C

Invalid input2

Enter text: 

第一个 CTRL-C 被困住了,它退出后不久,似乎主 goroutine 正在执行 r := bufio.NewReader(os.Stdin)


当我稍后按 CTRL-C 作为输入时,它被简单地视为文本并且不会调用信号处理程序。


我的代码如下(goplay 链接:http ://play.golang.org/p/LiKZMYGr00 )


package main


import ("fmt"

    "bufio"

    "os"

    "os/signal"

    "syscall"

    "io"

    "strings"

)


func main() {

    c := make(chan os.Signal)

    intr := make(chan bool)


    signal.Notify(c,  syscall.SIGINT)

    go func() {

        s := <-c

        fmt.Println("Got signal", s)

        fmt.Println("Exiting signal handler..")

        intr <- true

        return

    }()


breakOutOfHere:

    for {

        select {

        case <-intr:

            fmt.Println("Interrupted.. Continuing")

            continue

        default:

            fmt.Printf("Enter text: ")

            r := bufio.NewReader(os.Stdin)

            text, ret := r.ReadString('\n')

            if ret == io.EOF {

                fmt.Println("Invalid input1")

                continue

            } else if ret == nil {

                text = strings.TrimSpace(text)

                if text == "" {

                    fmt.Println("Invalid input2")

                    continue

                } else {

                    fmt.Printf("Entered:%s\n", text)

                    break breakOutOfHere

                }

            }

        }

    }

}


慕娘9325324
浏览 172回答 1
1回答

茅侃侃

signal.Notify向指定的通道发送信号信息,每次进程收到信号。但是在您的代码中,在第一个信号之后,go 例程完成。因此,它无法再次捕获信号。一种简单的方法是,您需要在 go 例程中使用带有 select 子句的无限循环。go func(c chan os.Signal, quit chan bool) {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-c:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Got interrupt signal")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Exiting signal handler..")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; intr <- true&nbsp; &nbsp; &nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("quit")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}(c, quit)在这里,使用 Channelquit来请求 go-routine 干净地退出。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go