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.
CodePudding user response:
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
}