Communication
Good communication is as stimulating as black coffee, and just as hard to sleep after.
– Anne Morrow Lindbergh
In this chapter we are going to look at the building blocks in Go forcommunicating with the outside world. We will look at files, directories,networking and executing other programs. Central to Go’s I/O are the interfacesio.Reader
and io.Writer
. The io.Reader
interface specifies one methodRead(p []byte) (n int, err err)
.
Reading from (and writing to) files is easy in Go. This programonly uses the os
package to read data from the file /etc/passwd
.
package main
import (
"log"
"os"
)
func main() {
buf := make([]byte, 1024)
f, e := os.Open("/etc/passwd") 1
if e != nil {
log.Fatalf(e)
}
defer f.Close() 2
for {
n, e := f.Read(buf) 3
if e != nil {
log.Fatalf(e) 4
}
if n == 0 { 5
break
}
os.Stdout.Write(buf[:n]) 6
}
}
We open the file at 1 with os.Open
that returns a os.File
os.File
implements io.Reader
and io.Writer
interface.After the Open
we directly put the f.Close()
which we defer until the functionreturn. At 3 we call Read
on f
and read up to 1024 bytes at the time. If anythingfails we bail out at 4. If the number of bytes read is 0 we’ve read the end of thefile 5. And at 6 we output the buffer to standard output.
If you want to use buffered I/O there is thebufio
package:
package main
import (
"bufio"
"log"
"os"
)
func main() {
buf := make([]byte, 1024)
f, e := os.Open("/etc/passwd") 1
if e != nil {
log.Fatalf(e)
}
defer f.Close()
r := bufio.NewReader(f) 2
w := bufio.NewWriter(os.Stdout)
defer w.Flush() 3
for {
n, e := r.Read(buf) 4
if e != nil {
log.Fatalf(e)
}
if n == 0 {
break
}
w.Write(buf[0:n]) 5
}
}
Again, we open 1 the file. Then at 2 weTurn f
into a buffered Reader
. NewReader
expects an io.Reader
, so you this will work.Then at 4 we read and at 5 we write. We also call Flush()
at 3 to flush all output.This entire program could be optimized further by using io.Copy
.