从标准输入读取行直到特定字符

I'm learning Go.

My program should read data from stdin until I enter a line with a single period.

package main

import (

  "os"
  "fmt"
  "bufio"

)

func main(){

  in    := bufio.NewReader(os.Stdin)
  input := ""

  for input != "." {
    input, err := in.ReadString('
')
    if err != nil {
      panic(err)
    }
  }
}

How I should modify my for loop, to stop the program when I enter a single dot ?

I tried to implement a while loop with the for statement, is there something wrong with my approach, is the condition wrong, or is ReadString messing with my data ?

... is ReadString messing with my data?

No, it isn't. It is reading up to the next ' '. That means that a line with only a dot on it will have the data ". " or ". " depending on the operating system.

To remove line endings, I would do input = strings.TrimRight(input, " ")

Just in case anybody else comes across this question:

Since Go 1.1 there's a much nicer way of looping over the lines of some input available. This is how I would tackle OP's problem today:

package main

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

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        line := scanner.Text()
        if line == "." {
            break
        }
        fmt.Println(line) // or do something else with line
    }
}

scanner.Text() automatically strips the trailing newline.

The main problem with using any bufio helper function is that it may read some more data beyond stop character ' '. It reads all available input up to the size of the buffer. In case of concurrent access to os.Stdin the next reader may miss some input that was read by bufio before it. Below is my non buffered "draft" code to sketch concurrent safe method of reading from input stream all characters up to CR (' ') char.

package main

import "os"

// echo a line in input to output
// you may add exit signal in copy loop as well
func main() {
    const BUF_SIZE = 128
    in := os.Stdin
    out := os.Stdout
    bufOut := make([]byte, BUF_SIZE)
    n := 0
    for {    // copy loop 
        // non buffered byte-by-byte
        if _, err := in.Read(bufOut[n : n+1]); err != nil {
            break
        }
        if bufOut[n] == 0xa || n == BUF_SIZE { // reached CR or size limit 
            if _, err = out.Write(bufOut[0 : n+1]); err != nil {
                break
            }
            n = 0
        } else {
            n++
        }
    }
}

Just noticed that question inside the topic is not same as in title. The error with initial sample in question is with input variable been re declared inside the loop. That is why your condition check never gets to the exit point.