英文:
How to wait for user input in go generate script?
问题
我正在为一个项目开发一个代码生成器,有时需要在继续之前等待用户输入。然而,我发现当通过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
运行,循环的每一次迭代后会等待我按回车键,然后再进行下一次迭代。通过go generate generate.go
运行,循环会一直迭代而不等待。
你可能会注意到,我实际上并不需要从用户那里读取任何数据,我只需要从用户那里得到一些反馈,告诉我他们已经完成了文件的更新。如果有其他方法可以让程序在用户完成后暂停,那也可以。
注意:我还尝试过使用bufio.Reader
、fmt.Scanln()
和io.ReadAll(os.Stdin)
代替bufio.Scanner
,但结果相同。
英文:
I'm working on a code generator for a project and sometimes need to wait for user input before proceeding. However, I'm finding that the usual methods of reading user input do not wait for the user to enter something before moving on when run through go generate
. However, if I run the script in the usual go run
way, the program waits for user input as expected (this is not an option for me though).
What I'm asking is: is there a way to have a program hang and wait for user input when run through go generate
?
I've seen How can I read from standard input in the console? and, while related, this is not exactly the same question.
Here's a sample:
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
Running go run main.go
, a single iteration of the loop executes and then waits for me to hit return before moving to the next iteration. Running go generate generate.go
, the loop iterates over and over without waiting.
You'll likely notice that I don't really need to read any data from the user, instead I only need to get some sort of feedback from the user that they are done updating the file. If there's another way to have the program hang until the user is done, that would be fine as well.
Note: I've also tried using bufio.Reader
, fmt.Scanln()
, and io.ReadAll(os.Stdin)
instead of bufio.Scanner
but get the same result.
答案1
得分: 2
go generate generate.go
将使用 exec.Command
分叉 main.go
,go generate
没有为 main.go
设置 stdin
,因此 main.go
无法从 os.Stdin
读取键盘输入。
另一种方法是直接从 /dev/tty
(Unix)或系统 API(Windows)读取键盘事件:
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("文件需要手动更新。")
log.Println("解决后按下 [RETURN] 键。")
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
}
英文:
go generate generate.go
will fork main.go
using exec.Command
, go generate
did not set a stdin
for main.go
, so main.go
could not read keyboard input from os.Stdin
.
Another way is reading keyboard event directly from /dev/tty
(unix) or 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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论