如何在 go generate 脚本中等待用户输入?

How to wait for user input in go generate script?

我正在为一个项目开发代码生成器,有时需要等待用户输入才能继续。但是,我发现当 运行 到 go generate 时,读取用户输入的常用方法不会等待用户输入内容后再继续。但是,如果我 运行 以通常的 go run 方式编写脚本,程序会按预期等待用户输入(尽管这对我来说不是一个选项)。

我要问的是:当 运行 到 go generate 时,有没有办法让程序挂起并等待用户输入?

我看过 How can I read from standard input in the console?,虽然相关,但这不是完全相同的问题。

这是一个示例:

main.go

package main

import (
    "bufio"
    "log"
    "os"
)

func main() {
    for isFileOk := checkFile(); !isFileOk; {
        log.Println("File requires manual update.")
        log.Println("Hit [RETURN] when resolved.")

        scanner := bufio.NewScanner(os.Stdin)
        for scanner.Scan() {
            break
        }
        isFileOk = checkFile()
    }
}

func checkFile() bool {
    return false
}

generate.go

package main

//go:generate go run main.go

运行 go run main.go,执行循环的单个迭代,然后等待我点击 return,然后再进行下一次迭代。 运行go generate generate.go,循环遍历,无需等待。

您可能会注意到,我实际上并不需要从用户那里读取任何数据,相反,我只需要从用户那里获得某种他们已完成文件更新的反馈。如果有另一种方法可以让程序挂起直到用户完成,那也很好。


注意:我也尝试过使用 bufio.Readerfmt.Scanln()io.ReadAll(os.Stdin) 而不是 bufio.Scanner,但得到的结果相同。

go generate generate.gofork main.go usingexec.Commandgo generate没有为main.go设置一个stdin,所以main.go可以不从 os.Stdin.

读取键盘输入

另一种方法是直接从 /dev/tty(unix) 或系统 API(win):

读取键盘事件
package main

import (
        "fmt"
        "log"

        "github.com/eiannone/keyboard"
)

func main() {
        if err := keyboard.Open(); err != nil {
                panic(err)
        }
        defer func() {
                _ = keyboard.Close()
        }()

        for isFileOk := checkFile(); !isFileOk; {
                log.Println("File requires manual update.")
                log.Println("Hit [RETURN] when resolved.")

                char, key, err := keyboard.GetKey()
                if err != nil {
                        panic(err)
                }
                fmt.Println(char, key, err)

                if key == keyboard.KeyEsc {
                        return
                }
        }
}

func checkFile() bool {
        return false
}