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 關注
- 168 瀏覽
添加回答
舉報