golang accepting input with spaces
Asked Answered
W

4

28

I'm just starting with GO and I understand that SCANF uses spaces as a separator in GO.

fmt.Scanf("%s",&input)

I cant really find a way to accepts inputs that contain spaces as valid characters.

Williford answered 11/12, 2014 at 2:52 Comment(4)
You've said you don't want to treat the space character as a delimiter. What characters would count as delimiters?Headspring
When the user presses enter it signifies the end of inputWilliford
this should be closed - no longer relevant with any later versions of go it shows as the top answer in google and wastes everyone's timeBrickle
@Williford I have edited my 2014 answer to include a better solution.Thadeus
T
-7

My initial 2014 answer used fmt.Scanln for this specific use case.
But fmt.Scanln also treats spaces as separators between inputs. That means it cannot directly read an entire line including spaces into a single string variable without additional handling.


A better option would be to use bufio.NewReader and its ReadString method.
Unlike fmt.Scanln, bufio.NewReader with ReadString allows you to read an entire line of input, including spaces, into a single string until a newline character is encountered. That behavior is precisely what is needed to accept inputs like "Hello there" as a single string.

Using fmt.Scanln:        "Hello there" → "Hello"
Using bufio.NewReader:   "Hello there" → "Hello there"

Using bufio.NewReader to read a line of input, including spaces, until the user presses Enter (newline), would be:

package main

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

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Enter text: ")
    input, err := reader.ReadString('\n') // '\n' is the delimiter to stop reading
    if err != nil {
        fmt.Println(err)
        return
    }

    // Trim the newline character from the input, if any
    input = strings.TrimSpace(input) 

    fmt.Println("You entered:", input)
}

You can test it on playground go.dev/play.

Remember, the ReadString method returns the delimiter as part of the input, so you may want to trim the input string to remove the newline character at the end.

Thadeus answered 11/12, 2014 at 6:30 Comment(5)
The program runs by itself and does not wait for the user input when I use this function.Williford
@Williford strange considering their respective implementations (github.com/golang/go/blob/…)Thadeus
The referenced doc mentions Scan. From Scan: "... storing successive space-separated values into successive arguments." If you want to capture the whole input from stdin, I suggest bufio.NewScanner(os.Stdin).Scrawly
this does not the solve the problem of taking a string containing spaces as input. ie mystr = "Hello there"Newsletter
@av192, note that if you pass the variable itself, instead of the address of the variable ( fmt.Scanln(var) instead of fmt.Scanln(&var) ), the issue of the program not waiting for user input crops up. Can someone throw light on the reason behind this behaviour?Kneel
P
43

you can use bufio.Reader and os.Stdin:

import(
  "bufio"
  "os"
)

in := bufio.NewReader(os.Stdin)

line, err := in.ReadString('\n')
Phlyctena answered 12/6, 2015 at 14:49 Comment(6)
Could you please elaborate more your answer adding a little more description about the solution you provide?Demona
I think the solution is to get input by the use of "bufio" library in golang. golang.org/pkg/bufioPhlyctena
The read string will be This is a string\n whereas I wanted it to be This is a string.Archipelago
Golang v1.2.0 works for me with another way: go in := bufio.NewReader(os.Stdin) line, err = in.ReadString('\n') Without ":=", only equals symbolSternpost
this is the wrong answer, it will output: <nil>YOURIUNPUT\nBrickle
this is wrong, it returns <nil>YOURINPUT\nBrickle
S
38

Similar to @chlin's answer, use bufio to capture whole lines.

The fmt Scan methods store each space separated value into a successive arguments. Three arguments on stdin would require something like:

package main

import "fmt"

func main() {
    var day, year int
    var month string
    fmt.Scanf("%d %s %d", &day, &month, &year)
    fmt.Printf("captured: %d %s %d\n", day, month, year)
}

If you don't know the full format of what you will be reading and just want the line, use bufio:

package main

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

func main(){
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Scan() // use `for scanner.Scan()` to keep reading
    line := scanner.Text()
    fmt.Println("captured:",line)
}
Scrawly answered 19/2, 2017 at 17:1 Comment(1)
What would you adapt here to make it take n inputs?Diplo
B
1

When using ReadString('\n'), it reads until and including the newline character. If you want to remove this trailing newline from the input string, you can use the strings.TrimSpace function.

package main

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

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Please enter a string: ")
    text, _ := reader.ReadString('\n')
    text = strings.TrimSpace(text)  // Remove any surrounding whitespace including the newline.
    fmt.Printf("You entered: %s", text)
}
Brickle answered 13/9, 2023 at 2:37 Comment(0)
T
-7

My initial 2014 answer used fmt.Scanln for this specific use case.
But fmt.Scanln also treats spaces as separators between inputs. That means it cannot directly read an entire line including spaces into a single string variable without additional handling.


A better option would be to use bufio.NewReader and its ReadString method.
Unlike fmt.Scanln, bufio.NewReader with ReadString allows you to read an entire line of input, including spaces, into a single string until a newline character is encountered. That behavior is precisely what is needed to accept inputs like "Hello there" as a single string.

Using fmt.Scanln:        "Hello there" → "Hello"
Using bufio.NewReader:   "Hello there" → "Hello there"

Using bufio.NewReader to read a line of input, including spaces, until the user presses Enter (newline), would be:

package main

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

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Enter text: ")
    input, err := reader.ReadString('\n') // '\n' is the delimiter to stop reading
    if err != nil {
        fmt.Println(err)
        return
    }

    // Trim the newline character from the input, if any
    input = strings.TrimSpace(input) 

    fmt.Println("You entered:", input)
}

You can test it on playground go.dev/play.

Remember, the ReadString method returns the delimiter as part of the input, so you may want to trim the input string to remove the newline character at the end.

Thadeus answered 11/12, 2014 at 6:30 Comment(5)
The program runs by itself and does not wait for the user input when I use this function.Williford
@Williford strange considering their respective implementations (github.com/golang/go/blob/…)Thadeus
The referenced doc mentions Scan. From Scan: "... storing successive space-separated values into successive arguments." If you want to capture the whole input from stdin, I suggest bufio.NewScanner(os.Stdin).Scrawly
this does not the solve the problem of taking a string containing spaces as input. ie mystr = "Hello there"Newsletter
@av192, note that if you pass the variable itself, instead of the address of the variable ( fmt.Scanln(var) instead of fmt.Scanln(&var) ), the issue of the program not waiting for user input crops up. Can someone throw light on the reason behind this behaviour?Kneel

© 2022 - 2025 — McMap. All rights reserved.