我想从命令行读取标准输入,但是在提示我输入之前,我的尝试以结束程序退出而告终。 我正在寻找C#中的Console.ReadLine()等效项。

这是我目前拥有的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
   "bufio"
   "fmt"
   "os"
)

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Enter text:")
    text, _ := reader.ReadString('
')
    fmt.Println(text)

    fmt.Println("Enter text:")
    text2 :=""
    fmt.Scanln(text2)
    fmt.Println(text2)

    ln :=""
    fmt.Sscanln("%v", ln)
    fmt.Println(ln)
}
  • 此代码看起来正确。 出于好奇,您正在操场上运行此游戏吗? 由于联网原因,Go Playground不允许标准输入。
  • @Jsor Im在本地运行。
  • 没关系,这似乎是一个微妙的问题,您需要一个指针(请参阅我的回答)。 虽然我不确定bufio.NewReader方法的问题是什么,因为它对我有用。
  • 从GO的初始stdin读取的可能重复项?
  • 不要将任何读取器(例如bufio.NewReader(os.Stdin))的bufio缓冲与从下划线读取器(例如fmt.Scanln(x)直接从os.Stdin直接读取)的直接读取混合使用。 缓冲可以任意向前读取。 (在这种特定情况下,后者应为fmt.Fscanln(reader,x)以便从同一缓冲区读取)。
  • 我没有得到fmt.Sscanln的效果,运行后它变为"%v"

我不确定块有什么问题

1
2
3
4
5
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter text:")
text, _ := reader.ReadString('
')
fmt.Println(text)

因为它可以在我的机器上使用。但是,对于下一个块,您需要一个指针,该指针指向要将输入分配给它们的变量。尝试用fmt.Scanln(&text2)替换fmt.Scanln(text2)。不要使用Sscanln,因为它会解析内存中已有的字符串,而不是stdin中的字符串。如果您想做类似您想做的事情,请将其替换为fmt.Scanf("%s", &ln)

如果仍然无法解决问题,您的罪魁祸首可能是某些奇怪的系统设置或错误的IDE。

  • 你是对的!我在Windows上使用GoSublime,它在那里不起作用,但是切换到字符串指针后在命令提示符下起作用。奇怪的是,bufio.NewReader(os.Stdin)之前都没有在命令提示符下工作。
  • 那些应该是单引号吗? ReadString(
    )
    ReadString("
    ")
  • @ 425nesp是的,多数民众赞成在分隔符,这是一个字节。 golang.org/pkg/bufio/#Reader.ReadString
  • 好的答案,但是当我尝试使用退格键等失败
  • 对于Golang来说,通过读取器rd从文件读取行到变量sif s,_ = rd.ReadString(
    ); true { s = strings.Trim(s,"
    ") }
    是如此多
  • 只是分享一件有趣的事情(我是Golang初学者): n必须在单引号内(不要尝试使用双引号)。否则,它将重现此内容:cannot use"
    " (type string) as type byte in argument to reader.ReadString
  • 如果执行此操作,显然text将具有结尾的?

您也可以尝试:

1
2
3
4
5
6
7
8
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
    fmt.Println(scanner.Text())
}

if scanner.Err() != nil {
    // handle error.
}
  • 这是阅读stdin的一种很好,简洁的方法!
  • 如果您只想输入一个一行,则可以删除" for {}"。
  • 如果有for {}循环,如何在进入时从循环中出来?是否存在使循环停止的特殊字符? - 谢谢
  • @Madhan Scanner.Scan()返回布尔值,以指示是否退出for循环。
  • 如果输入大于64 * 1024字节,则会收到此错误bufio.Scanner:令牌太长。同样不要忘记在for循环下面添加fmt.Println(scanner.Err())
  • 如果我输入" abc n ^ D",期望的字符串是" abc n",但返回" abc",该怎么办。
  • @YuvarajLoganathan我们可以将大小(64 * 1024字节)增加到无限吗?
  • 我们不能增加限制。它被硬编码到go运行时中。

我认为更标准的方法是:

1
2
3
4
5
6
7
8
9
10
package main

import"fmt"

func main() {
    fmt.Print("Enter text:")
    var input string
    fmt.Scanln(&input)
    fmt.Print(input)
}

看看scan godoc:http://godoc.org/fmt#Scan

Scan scans text read from standard input, storing successive space-separated values into successive arguments. Newlines count as space.

Scanln is similar to Scan, but stops scanning at a newline and after the final item there must be a newline or EOF.

  • 这似乎不喜欢输入字符串中的空格。
  • @HairyChris是的,这很奇怪。在文档中它表示stops scanning at a newline and after the final item there must be a newline or EOF,所以不确定为什么空间会"破坏"它...我想这是一个错误
  • 为此打开了一个错误:github.com/golang/go/issues/5703它已作为WorkingAsIntended关闭。另请参阅:stackoverflow.com/questions/24005899/和groups.google.com/forum/#!topic/golang-nuts/r6Jl4D9Juw0似乎很多人对此都有疑问。需要更改文档吗?同样,从最后一个链接开始:" Scan和Scanln用于解析之类的东西,因此仅从stdin中获取一行文本就无法达到目的。"
  • 对我来说,fmt.Scan的任何类似功能都让它感到困惑,在bufio.NewReader这样的空间中无法很好地发挥作用。
  • 在当前的2016 go版本(go版本go1.6.2 linux / amd64)中使用fmt.Scanlnfmt.Scan时,仍然存在空格问题。
  • 空格行不适用于fmt.Scanln()

始终尝试使用bufio.NewScanner从控制台收集输入。正如其他人提到的那样,有多种方法可以完成这项工作,但Scanner最初是打算完成这项工作的。 Dave Cheney解释了为什么应使用Scanner而不是bufio.Reader的ReadLine。

这是您的问题的代码片段答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import (
   "bufio"
   "fmt"
   "os"
)

/*
 Three ways of taking input
   1. fmt.Scanln(&input)
   2. reader.ReadString()
   3. scanner.Scan()

   Here we recommend using bufio.NewScanner
*/

func main() {
    // To create dynamic array
    arr := make([]string, 0)
    scanner := bufio.NewScanner(os.Stdin)
    for {
        fmt.Print("Enter Text:")
        // Scans a line from Stdin(Console)
        scanner.Scan()
        // Holds the string that scanned
        text := scanner.Text()
        if len(text) != 0 {
            fmt.Println(text)
            arr = append(arr, text)
        } else {
            break
        }

    }
    // Use collected inputs
    fmt.Println(arr)
}

如果您不想以编程方式收集输入,只需添加以下行

1
2
3
4
   scanner := bufio.NewScanner(os.Stdin)
   scanner.Scan()
   text := scanner.Text()
   fmt.Println(text)

上面程序的输出将是:

1
2
3
4
5
6
Enter Text: Bob
Bob
Enter Text: Alice
Alice
Enter Text:
[Bob Alice]

上面的程序收集用户输入并将其保存到数组中。我们还可以使用特殊字符来中断该流程。扫描仪提供API以供高级使用,例如使用自定义函数进行拆分等,扫描不同类型的I / O流(Stdin,String)等。


在循环中读取多个输入的另一种方法可以处理带空格的输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
import (
   "fmt"
   "bufio"
   "os"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    var text string
    for text !="q" {  // break the loop if text =="q"
        fmt.Print("Enter your text:")
        scanner.Scan()
        text = scanner.Text()
        if text !="q" {
            fmt.Println("Your text was:", text)
        }
    }
}

输出:

1
2
3
4
5
Enter your text: Hello world!
Your text was:  Hello world!
Enter your text: Go is awesome!
Your text was:  Go is awesome!
Enter your text: q
  • 您可能只需要在内部的" q"检查中使用一个break并将其包装在无限循环中即可。好的答案!
  • 看起来您现在也可以在for循环中摆脱条件。

我迟到了。但是一个班轮怎么样:

1
data, err := ioutil.ReadAll(os.Stdin)
  • 因为os.Stdin不会结束,所以无法全部阅读。您可能正在等待一段时间...
  • 按ctrl + d,即eot。
  • 是的,那就做到了-让我想起用mail编写电子邮件。
  • 或任何接受stdin的Linux命令。

试试这个代码:

1
2
3
4
5
6
var input string
func main() {
      fmt.Print("Enter Your Name=")
      fmt.Scanf("%s",&input)
      fmt.Println("Hello"+input)
      }
  • 似乎Scanf()不接受字符串中的空格
  • 带有空格的行不适用于fmt.Scanln()

也可以这样:

1
2
3
4
5
6
7
8
package main
import"fmt"    

func main(){
    var myname string
fmt.Scanf("%s", &myname)          
fmt.Println("Hello", myname)      
}

干净地读取几个提示值:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Create a single reader which can be called multiple times
reader := bufio.NewReader(os.Stdin)
// Prompt and read
fmt.Print("Enter text:")
text, _ := reader.ReadString('
')
fmt.Print("Enter More text:")
text2, _ := reader.ReadString('
')
// Trim whitespace and print
fmt.Printf("Text1: "%s", Text2: "%s"
",
    strings.TrimSpace(text), strings.TrimSpace(text2))

运行:

1
2
3
Enter text: Jim
Enter More text: Susie
Text1:"Jim", Text2:"Susie"
  • 这也是一个好方法,因为strings.TrimSpace删除了 n。而且我相信reader.ReadString( n)也是跨平台的。
  • 我猜想大多数情况下您想默认删除 n,这就是为什么它更好的原因bufio.NewScanner as @Naren Yellavula answer

就我而言,程序没有等待,因为我正在使用watcher命令自动运行程序。手动运行程序go run main.go导致"输入文本"并最终打印到控制台。

1
2
3
4
fmt.Print("Enter text:")
var input string
fmt.Scanln(&input)
fmt.Print(input)

您需要提供一个指向您要扫描的var的指针,如下所示:

1
fmt.scan(&text2)