Files
learngo/interfaces/16-io-compose/main.go

77 lines
1.8 KiB
Go
Raw Normal View History

2019-11-06 20:52:51 +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 (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"os"
)
func main() {
resp, err := http.Get("https://inancgumus.github.com/x/rosie.unknown")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
2019-11-06 20:52:51 +03:00
}
defer resp.Body.Close()
// creates a file (or truncates if the file exists)
file, err := os.Create("rosie.png")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
2019-11-06 20:52:51 +03:00
}
defer file.Close()
n, err := transfer(resp.Body, file)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
2019-11-06 20:52:51 +03:00
}
fmt.Printf("%d bytes transferred.\n", n)
2019-11-08 11:40:39 +03:00
// main() runs the deferred funcs in reverse order:
2019-11-06 20:52:51 +03:00
// file.Close()
// resp.Body.Close()
}
// transfer streams data from a reader to a writer.
// if the reader doesn't contain a PNG signature, transfer returns errNotPNG.
// otherwise, it transfers the data to the writer.
func transfer(r io.Reader, w io.Writer) (n int64, err error) {
const pngSign = "\x89PNG\r\n\x1a\n"
const pngSignLen = 8
var memory bytes.Buffer
// limit what copy() reads.
// lr := io.LimitReader(r, pngSignLen)
// if n, err = io.Copy(&memory, lr); err != nil {
// return n, err
// }
// same as above. behind the scenes CopyN() calls LimitReader.
if n, err = io.CopyN(&memory, r, pngSignLen); err != nil {
return n, err
}
// check the png signature.
if !bytes.HasPrefix(memory.Bytes(), []byte(pngSign)) {
return n, errors.New("not png")
2019-11-06 20:52:51 +03:00
}
// stitch the PNG signature (memory) and the response body reader together.
// then copy them successively to the writer (*os.File).
return io.Copy(w, io.MultiReader(&memory, r))
}