I was watching this talk given at FOSDEM '17 about implementing “tail -f” in Go => https://youtu.be/lLDWF59aZAo
In the author’s initial example program, he creates a Reader using a file handle, and then uses the ReadString method with delimiter ‘\n’ to read the file line by line and print its contents.
Program below
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
fileHandle, err := os.Open("someFile.log")
if err != nil {
log.Fatalln(err)
return
}
defer fileHandle.Close()
reader := bufio.NewReader(fileHandle)
for {
line, err := reader.ReadString('\n')
if err != nil {
log.Fatalln(err)
break
}
fmt.Print(line)
}
}
Now, ReadString takes a byte as its delimiter argument[bufio package - bufio - Go Packages]
So my question is, how in the world did ‘\n’, which is a rune, get converted into a byte? I am not able to get my head around this. Especially since byte is an alias for uint8, and rune is an alias for int32.
I asked the same question in Gophers slack, and was told that ‘\n’ is not a rune, but an untyped constant. If we actually created a rune using ‘\n’ and passed it in, the compilation would fail. This actually confused me a bit more.
I was also given a link to a section of the Go spec regarding Type Identity => The Go Programming Language Specification - The Go Programming Language
If the program is not supposed to compile if it were an actual rune, why does the compiler allow an untyped constant to go through? Isn’t this unsafe behaviour?
My guess is that this works due to a rule in the Assignability section in the Go spec (The Go Programming Language Specification - The Go Programming Language), which says
x is an untyped constant representable by a value of type T.
Since ‘\n’ can indeed be assigned to a variable of type byte, it is therefore converted.
Is my reasoning correct?
Thanks,
Krishna Kishore Shetty