package main
import (
"fmt"
"os"
"bufio"
)
var counter int = 0
func main() {
var (
read1 *bufio.Scanner;
)
read1 = bufio.NewScanner(os.Stdin);
read2 := read1
count_lines(read1)
read2.Scan()
fmt.Println("read2: ", read2.Text())
os.Exit(0);
}
func count_lines(read *bufio.Scanner){
read.Scan();
fmt.Println("read1: ", read.Text())
if read.Text() == ""{
return;
}
counter ;
count_lines(read);
}
So, I'm trying to count lines of my user input using recursion. And I also want to work on the same input in a different function. But when I use Scan(), it parses through the input line by line once. The read2 variable is empty. Is there a way to properly copy the user input? I'm sorry if I couldn't explain properly. I'm new to Go and I don't understand any of it. I've attached an image for reference. reference Thank You.
CodePudding user response:
Welcome to StackOverflow, and Go!
I'll try to explain the situation in a hopefully understandable and not necessarily technically accurate way.
So, in order to read input from the keyboard you're using a 'scanner' that you 'named' read1
:
read1 = bufio.NewScanner(os.Stdin)
Then you 'copied' that 'scanner' and named it read2
read2 := read1
So now when you call count_lines
with the read1
scanner you count the lines until an empty line is entered.
And, then, you assumed that when you're done with the line counting, read2
will be able to read the same lines again. But this isn't how it works.
What actually happens is better illustrated with the following. Imagine read1
and read2
are two pickaxes ⛏️ that you can use to dig something out of the ground.
So you take a pickaxe you kindly named read1
and hit a ground (this is equal to read.Scan()
). Then you pick up the piece you got and check what is inside (read.Text()
). You, then, repeat the process until you're done pickaxing or until - read.Text() == ""
.
When you're done, you take the ⛏️ named read2
and... You cannot pickaxe the same thing again, right? And that is basically how the scanner works.
So to deal with it you can say to yourself, I don't need two pickaxes, one is enough but whatever I excavated from the ground I want to keep and analyze it first for diamonds (count_lines) and then in the second pass for gold (or whatever you like).
So your code might look like:
package main
import (
"fmt"
"os"
"bufio"
)
var counter int = 0
var myLines = ""
func main() {
var (
read1 *bufio.Scanner;
)
read1 = bufio.NewScanner(os.Stdin);
count_lines(read1)
fmt.Println("read2: ");
fmt.Println(myLines)
os.Exit(0);
}
func count_lines(read *bufio.Scanner) {
read.Scan();
line := read.Text();
myLines = line "\n";
fmt.Println("read1: ", line)
if read.Text() == ""{
return;
}
counter ;
count_lines(read);
}
Note: This is not the idiomatic (recommended) way of doing things. I aimed at changing as little of the original code as possible.