【问题标题】:Golang - Read Os.stdin input but don't echo itGolang - 读取 Os.stdin 输入但不回显它
【发布时间】:2016-06-29 08:46:18
【问题描述】:

在 golang 程序中,我从 bufio.Reader 读取 Os.Stdin 输入。

按下回车后,程序读取输入,然后将其打印到控制台。是否可以不将输入打印到控制台上?读完后,我处理输入并重新打印(不再需要原始输入)。

我是这样读取数据的:

inputReader := bufio.NewReader(os.Stdin)
for {
    outgoing, _ := inputReader.ReadString('\n')
    outs <- outgoing
}

【问题讨论】:

    标签: input go stdin


    【解决方案1】:

    除了使用ANSI escape codes 来清除终端并将光标移动到特定位置(在您的情况下移动到第 1 列:第 1 行)之外,我想不出其他方法。

    var screen *bytes.Buffer = new(bytes.Buffer)
    var output *bufio.Writer = bufio.NewWriter(os.Stdout)
    

    这里有一些基本的辅助方法可以帮助您轻松使用终端。

    // Move cursor to given position
    func moveCursor(x int, y int) {
        fmt.Fprintf(screen, "\033[%d;%dH", x, y)
    }
    
    // Clear the terminal
    func clearTerminal() {
        output.WriteString("\033[2J")
    }
    

    然后在您的函数中,您需要清除终端并将光标移动到终端窗口的第一列和第一行。最后你必须输出计算结果。

    for {
        outgoing, err := input.ReadString('\n')
    
        if err != nil {
            break
        }
    
        if _, err := fmt.Sscanf(outgoing, "%f", input); err != nil {
            fmt.Println("Input error!")
            continue
        }
    
        // Clear console
        clearTerminal()
        moveCursor(1,1)
    
        fmt.Println(outs) // prints the computed result
    }
    

    【讨论】:

      【解决方案2】:

      您似乎正在寻找特定于终端的功能来禁用回声。这通常在终端上写密码时使用(可以输入但看不到字符)。

      我建议你尝试一下terminal.ReadPassword,它应该可以很好地工作,并且可能以最跨平台兼容的方式。

      prompt := ""
      t := terminal.NewTerminal(os.Stdin, prompt)
      for {
          outgoing, err := t.ReadPassword(prompt)
          if err != nil {
              log.Fatalln(err)
          }
          outs <- outgoing
      }
      

      【讨论】:

      • 如果您从 Cygwin 或 Msys2 bash 提示符之类的东西中运行 go 生成的 .exe,这在 Windows 上不起作用。还有其他方法吗?
      • @GodEater 这要么是 Go 库中的错误,要么是 Cygwin 或 Msys2 如何在 Windows 中实现 bash 的错误。除此之外我不知道,对不起。
      • 根据文档,您应该先将终端置于原始模式,并且终端包有一个 MakeRaw() 函数,但它需要一个文件描述符......大概是文件描述符在这种情况下适用于 os.Stdin,但我不知道如何获得它...
      【解决方案3】:

      除了加密/ssh/终端;

      package main
      
      import (
          "bufio"
          "fmt"
          "os"
          "os/exec"
      )
      
      func raw(start bool) error {
          r := "raw"
          if !start {
              r = "-raw"
          }
      
          rawMode := exec.Command("stty", r)
          rawMode.Stdin = os.Stdin
          err := rawMode.Run()
          if err != nil {
              return err
          }
      
          return rawMode.Wait()
      }
      
      // http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
      func main() {
          var rs []rune
          raw(true)
          for {
              inp := bufio.NewReader(os.Stdin)
              r, _, err := inp.ReadRune()
              if err != nil {
                  raw(false)
                  panic(err)
              }
      
              if r == '\x03' { // ctrl+c
                  break
              } else if r == '\r' { // enter
                  fmt.Print(string(rs), "\n\r")
                  rs = []rune{}
                  continue
              } else if r == '\u007f' { // backspace
                  fmt.Printf("\033[1D\033[K")
                  continue
              }
      
              rs = append(rs, r)
          }
      
          raw(false)
      }
      

      【讨论】:

      • 伟大的极客因素,但非常脆弱且以 *nix 为中心
      猜你喜欢
      • 2023-03-28
      • 2016-02-19
      • 2015-07-24
      • 2018-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-31
      • 2016-12-30
      相关资源
      最近更新 更多