Here's how to read a whole file then loop over the lines:
file, err := ioutil.ReadFile("data.txt")
// some error handling
for _, line := range strings.Split(file, "\n") {
fmt.Println(line)
}
Here's how to stream a file one line at a time: file, err := os.Open("data.txt")
// some error handling
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
// more error handling
}
Here's how I, at least, would like it to work: fileContents := file.Read("data.txt")
for _, line := range fileContents {
fmt.Println(line)
}
if fileContents.Err() {
// some error handling
}
fileContents := file.ReadStreaming("data.txt")
for _, line := range fileContents {
fmt.Println(line)
}
if fileContents.Err() {
// some error handling
}
The critical point is that I don't want to care whether `file` is a byte slice or a byte buffer, and Go doesn't let me not care. I want to be able to write code that deals with "enumerable data of some sort", once, and then works no matter how the caller decides to provide that data.Go (intentionally) makes it exceedingly difficult to obscure how a piece of code works from the rest of the codebase, and I personally think that's a fatally poor design decision. In my experience, it makes it difficult to decouple modules since code often has to be at least somewhat aware of quite a few implementation details of a library in order to use it correctly. It makes it really difficult to build higher level abstractions that don't leak. I have a much harder time in Go getting away from thinking in `int`s and `floats` and staying terms of the domain objects that I actually do care about.
"How" a piece of code functions is at best the third, and probably only the fourth most important question (behind "why", "what", and probably "when" if you use any concurrency at all), but Go forces it to be front and center at all times.