116 lines
2.7 KiB
Go
Raw Permalink Normal View History

2019-11-01 13:12:03 +03:00
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io"
"os"
)
func main() {
// Stdin, Stdout, and Stderr are *os.File.
// #1: reads from the standard input
// ------------------------------------------------
// if err := read(os.Stdin); err != nil {
// fmt.Fprintln(os.Stderr, err)
// return
2019-11-01 13:12:03 +03:00
// }
// #2: writes to the standard output
// ------------------------------------------------
// buf := []byte("hi!\n")
// if err := write(os.Stdout, buf); err != nil {
// fmt.Fprintln(os.Stderr, err)
// return
2019-11-01 13:12:03 +03:00
// }
// #2b: reads the entire file content into memory.
// ------------------------------------------------
// buf, err := ioutil.ReadFile("alice.txt")
// if err != nil {
// fmt.Fprintln(os.Stderr, err)
// return
2019-11-01 13:12:03 +03:00
// }
// if err := write(os.Stdout, buf); err != nil {
// fmt.Fprintln(os.Stderr, err)
// return
2019-11-01 13:12:03 +03:00
// }
// #3: reads and writes with 32KB of memory
// no matter how large the source data is.
// ------------------------------------------------
if err := ioCopy(os.Stdout, os.Stdin); err != nil {
fmt.Fprintln(os.Stderr, err)
return
2019-11-01 13:12:03 +03:00
}
}
2019-11-04 11:00:53 +03:00
// ioCopy streams from a file to another file.
// we use it to stream from the standard input to ouput.
2019-11-01 13:12:03 +03:00
func ioCopy(dst, src *os.File) error {
2019-11-02 11:21:35 +03:00
// Use a fixed-length buffer to efficiently read from src stream in chunks.
2019-11-01 13:12:03 +03:00
buf := make([]byte, 32768)
2019-11-02 11:21:35 +03:00
// read over and over again to read all the data.
2019-11-01 13:12:03 +03:00
for {
2019-11-02 11:21:35 +03:00
// read can read only up to the buffer length.
2019-11-01 13:12:03 +03:00
nr, er := src.Read(buf)
2019-11-02 11:21:35 +03:00
// only write data if there is something to write.
2019-11-01 13:12:03 +03:00
if nr > 0 {
_, ew := dst.Write(buf[:nr])
if ew != nil {
return ew
}
}
2019-11-02 11:21:35 +03:00
// io.EOF = there is nothing left to read—close the loop.
2019-11-01 13:12:03 +03:00
if er == io.EOF {
return nil
}
2019-11-02 11:21:35 +03:00
// Only return an error if the reading really fails.
2019-11-01 13:12:03 +03:00
if er != nil {
return er
}
}
return nil
}
// write example.
2019-11-01 13:12:03 +03:00
func write(dst *os.File, buf []byte) error {
nw, ew := dst.Write(buf)
fmt.Printf("wrote : %d bytes\n", nw)
fmt.Printf("write err: %v\n", ew)
return ew
}
// read example.
func read(src *os.File) error {
buf := make([]byte, 1024*32) // in the middle.
// buf := make([]byte, 148157) // defies the purpose of streaming.
// buf := make([]byte, 8) // too many chunking.
for {
nr, er := src.Read(buf)
// fmt.Printf("buf : %q\n", buf[0:nr])
fmt.Printf("read : %d bytes\n", nr)
fmt.Printf("read err : %v\n", er)
if er == io.EOF {
return nil
}
if er != nil {
return er
}
}
return nil
}