We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
The whole concept of the io.Reader
interface in Go is pure genius (the same applies to io.Writer
by the way). Recently, I wanted to inspect a .tar.gz file which was hosted on a server and I needed to extract a single file from it.
Normally, you would download the file to disk, gunzip it, untar it and then keep the file you want.
By using the io.Reader
interface, this task can be done withouy having to create all the temporary files:
package main
import (
"archive/tar"
"compress/gzip"
"io"
"net/http"
"os"
"time"
"github.com/pieterclaerhout/go-log"
)
func main() {
targetFilePath := "file-to-save"
httpClient := http.Client{
Timeout: 5 * time.Second,
}
req, err := http.NewRequest("GET", "https://server/file.tar.gz", nil)
log.CheckError(err)
resp, err := httpClient.Do(req)
log.CheckError(err)
uncompressedStream, err := gzip.NewReader(resp.Body)
log.CheckError(err)
tarReader := tar.NewReader(uncompressedStream)
for true {
header, err := tarReader.Next()
if err == io.EOF {
break
}
log.CheckError(err)
if header.Name == "the-file-i-am-looking-for" {
outFile, err := os.Create(targetFilePath)
log.CheckError(err)
defer outFile.Close()
_, err = io.Copy(outFile, tarReader)
log.CheckError(err)
break
}
}
}
The beauty is in these lines:
resp, err := httpClient.Do(req)
log.CheckError(err)
uncompressedStream, err := gzip.NewReader(resp.Body)
log.CheckError(err)
tarReader := tar.NewReader(uncompressedStream)
Since the response body from a HTTP client request is implementing the io.Reader
interface, you can wrap it in a gzip.Reader
. This basically allows you to get the tar file. That stream also implements io.Reader
which can then be "untarred" by feeding it into tar.Reader
.
You can find a full example of how this can be used in the DatabaseDownloader type of my GeoIP project.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.