Chris
Chris

Reputation: 515

Break out of input.Scan()

I have this simple code to read all input from the console:

input := bufio.NewScanner(os.Stdin) //Creating a Scanner that will read the input from the console

for input.Scan() {
    if input.Text() == "end" { break } //Break out of input loop when the user types the word "end"
    fmt.Println(input.Text())
}

The code as it is works. What I want to do is get rid of the if-clause. In my understanding of the documentation if a line is empty input.Scan() should return false and therefore break out of the loop.

Scan advances the Scanner to the next token, which will then be available through the Bytes or Text method. It returns false when the scan stops, either by reaching the end of the input or an error. After Scan returns false, the Err method will return any error that occurred during scanning, except that if it was io.EOF, Err will return nil. Scan panics if the split function returns 100 empty tokens without advancing the input. This is a common error mode for scanners.

Am I misinterpreting the documentation and it is actually necessary to have such a if-clause to break out? (I'm using Go 1.5.2 running the program using "go run".)

Upvotes: 24

Views: 13890

Answers (6)

Prem
Prem

Reputation: 432

For windows, the EOF for stdin is ctrl+Z, followed by enter.

Upvotes: 1

mc_pengzi
mc_pengzi

Reputation: 134

CTRL+D to break, if you want to input data easily, you can use cat input.txt | go run script.go or go run script.go < input.txt.

Upvotes: 7

Krishnadas PC
Krishnadas PC

Reputation: 6539

For Mac systems, you can try Ctrl + D to break by default. If you are at the end of the line you will have to hit Ctrl + D 2 times.

Upvotes: 1

Abhay Kumar
Abhay Kumar

Reputation: 550

You are not misinterpreting the documentation.

It returns false when the scan stops, either by reaching the end of the input or an error.

What documentation states is correct. But you are missing that you need a way to provide end of the input i.e. EOF from the console.

In linux you can press "CTRL+D", which signals EOF from terminal.

Though there is a small catch here, that "CTRL+D" works only at the beginning of the line. Thus to terminate the input from terminal you need to go to a new line and press "CTRL+D" as first input on the line.

Upvotes: 2

InkyDigits
InkyDigits

Reputation: 3228

Typing a blank new line will not automatically stop the scanner.

If it ain't broke, don't fix it--but you can make it behave as you require. This doesn't get rid of your if block but functions as you expected scanner to, i.e. hitting enter with no input will stop the scanner:

    input := bufio.NewScanner(os.Stdin) //Creating a Scanner that will read the input from the console

    for input.Scan() {
        if input.Text() == "" {
            break
        } 
        fmt.Println(input.Text())
    }

Upvotes: 10

Micka&#235;l R&#233;mond
Micka&#235;l R&#233;mond

Reputation: 9055

I think you misread the documentation. The default scanner is ScanLines function.

Documentation says:

ScanLines is a split function for a Scanner that returns each line of text, stripped of any trailing end-of-line marker. The returned line may be empty. The end-of-line marker is one optional carriage return followed by one mandatory newline. In regular expression notation, it is \r?\n. The last non-empty line of input will be returned even if it has no newline.

Two important points here:

  • The return line may be empty: It means it returns empty lines.
  • The last non-empty line of input will be returned even if it has no newline: It means the last line of a file is always returned if it is non empty. It does not mean however an empty line end the stream.

The scanner will stop on EOF (End Of File). Typing Ctrl-D for example will send end of file and stop the scanner.

Upvotes: 43

Related Questions