2 回答
TA贡献1802条经验 获得超6个赞
因此,您需要来自 Stdin(管道)和用户 Stdin(键盘)的并发输入:
我认为您的答案是 cat 命令,请参阅:如何将初始输入通过管道传输到进程中,然后该进程将是交互式的?
和:https://en.wikipedia.org/wiki/Cat_(Unix)
请参阅:如何在 Go 中通过管道传输多个命令?
并进行进程间通信
有 3 件事需要注意:
首先:检查所有错误是一个好习惯:
在您的情况下:
n, err := fmt.Scanln(&response)
第二:
您正在使用递归调用(Tail Call),这里没有必要。
用简单的 for 循环替换它并查看: Go
3 中的尾调用优化:
最后但并非最不重要的一点:如果输入错误,您的代码将永远循环(如果编译器无法优化尾调用,则消耗堆栈)!
最好限制在 3 个。
例如:
package main
import "fmt"
import "strings"
type Input int
const (
Timeout Input = iota
Yes
No
Abort
BadInput
)
func userInput(msg string) Input {
var input string
for i := 0; i < 3; i++ {
fmt.Println(msg)
n, err := fmt.Scanln(&input)
if n > 0 {
switch strings.ToLower(input) {
case "y":
return Yes
case "n":
return No
case "a":
return Abort
}
}
if err != nil {
return BadInput // or panic(err)
}
}
return Timeout
}
func main() {
ans := userInput("Please type Yes,No or Abort and then press enter [y/n/a]: ")
fmt.Println(ans)
switch ans {
case Yes:
fmt.Println("Yes") // do some job
//...
}
}
编辑:使用这个简单的“y/n”,您无需检查它是否是管道。
即使是带有一个字节切片的简单 std Read 也很好:
os.Stdin.Read(b1)
查看我的管道示例:https ://stackoverflow.com/a/37334984/6169399
但如果您的标准输入是管道,您可以使用:
bytes, err := ioutil.ReadAll(os.Stdin)
一次读取所有管道数据。但要小心处理错误。您可以检查标准输入是否与终端或管道相关联,然后使用适当的代码。
检测它的简单方法是否是管道:
package main
import (
"fmt"
"os"
)
func main() {
info, err := os.Stdin.Stat()
if err != nil {
fmt.Println("not a pipe")
} else {
fmt.Println("pipe name=", info.Name(), "pipe size=", info.Size())
}
}
全部在一个示例代码中:
package main
import (
"fmt"
"io/ioutil"
"os"
"strings"
)
type Input int
const (
Timeout Input = iota
Yes
No
Abort
BadInput
)
func userInput(msg string) Input {
var input string
for i := 0; i < 3; i++ {
fmt.Println(msg)
n, err := fmt.Scanln(&input)
if n > 0 {
switch strings.ToLower(input) {
case "y":
return Yes
case "n":
return No
case "a":
return Abort
}
}
if err != nil {
return BadInput // or panic(err)
}
}
return Timeout
}
func main() {
info, err := os.Stdin.Stat()
if err != nil {
//fmt.Println("not a pipe")
ans := userInput("Please type Yes,No or Abort and then press enter [y/n/a]: ")
fmt.Println(ans)
switch ans {
case Yes:
fmt.Println("Yes") // do some job
//...
}
} else {
fmt.Println("pipe name=", info.Name(), "pipe size=", info.Size())
bytes, err := ioutil.ReadAll(os.Stdin)
fmt.Println(string(bytes), err) //do some jobe with bytes
}
}
TA贡献1828条经验 获得超4个赞
您可以使用os.ModeCharDevice:
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
// piped
input, _ := ioutil.ReadAll(os.Stdin)
} else {
// not piped, do whatever, like fmt.Scanln()
}
- 2 回答
- 0 关注
- 194 浏览
添加回答
举报
