我正在为一个项目编写代码生成器,有时需要在继续之前等待用户输入。然而,我发现读取用户输入的通常方法在运行go generate
时不会等待用户输入一些东西。但是,如果我以通常的go run
方式运行脚本,程序将按照预期等待用户输入(尽管这不是我的选项)。
我要问的是:有没有一种方法可以让程序挂起并等待用户输入,当通过go generate
运行时?
我已经看到了如何在控制台中读取标准输入?虽然相关,但这不是完全相同的问题。
下面是一个示例:
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.Reader
,fmt.Scanln()
和io.ReadAll(os.Stdin)
而不是bufio.Scanner
,但得到相同的结果。
go generate generate.go
将使用exec.Command
派生main.go
,go generate
没有为main.go
设置stdin
,因此main.go
无法读取os.Stdin
的键盘输入。
另一种方法是直接从/dev/tty
(unix)或System 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
}