title: how to write a directory [not just the files in it ] to a tar.gz file in golang
body: <p>I want to write a tar_gz tool in Go. The input is just like linux command:</p>
  
  <pre><code>$tar czvf targetFileName inputDirectoryPath
  </code></pre>
  
  <p>Suppose I have an inputDirectory structured as below:</p>
  
  <pre><code>test [dir]
  -- 0.txt
      -- 1 [sub dir]
           -- 1.txt
  </code></pre>
  
  <p>For Example: use command:</p>
  
  <pre><code>$tar czvf test.tar.gz test/
  </code></pre>
  
  <p>we can tar and gzip the whole test directory.</p>
  
  <p><br> My Problem is I can write a tar and gz route to recursively iterate all the file in test directory and write the file to test.tar.gz file. But I don't know how to write a directory to the test.tar.gz. After running my program, the structure in test.tar.gz file is:</p>
  
  <pre><code>0.txt
  1.txt
  </code></pre>
  
  <p>Can anyone tell me how to write the directory recursively to the output tar.gz file. Thanks a lot.</p>
  
  <pre><code>    package main
  
      import (
        "fmt"
        "os"
        "io"
        "log"
        "strings"
        "archive/tar"
        "compress/gzip"
      )
  
      func handleError( _e error ) {
        if _e != nil {
          log.Fatal( _e )
        }
      }
  
      func TarGzWrite( _path string, tw *tar.Writer, fi os.FileInfo ) {
        fr, err := os.Open( _path )
        handleError( err )
        defer fr.Close()
  
        h := new( tar.Header )
        h.Name = fi.Name()
        h.Size = fi.Size()
        h.Mode = int64( fi.Mode() )
        h.ModTime = fi.ModTime()
  
        err = tw.WriteHeader( h )
        handleError( err )
  
        _, err = io.Copy( tw, fr )
        handleError( err )
      }
  
      func IterDirectory( dirPath string, tw *tar.Writer ) {
        dir, err := os.Open( dirPath )
        handleError( err )
        defer dir.Close()
        fis, err := dir.Readdir( 0 )
        handleError( err )
        for _, fi := range fis {
          curPath := dirPath + "/" + fi.Name()
          if fi.IsDir() {
            //TarGzWrite( curPath, tw, fi )
            IterDirectory( curPath, tw )
          } else {
            fmt.Printf( "adding... %s\n", curPath )
            TarGzWrite( curPath, tw, fi )
          }
        }
      }
  
      func TarGz( outFilePath string, inPath string ) {
        // file write
        fw, err := os.Create( outFilePath )
        handleError( err )
        defer fw.Close()
  
        // gzip write
        gw := gzip.NewWriter( fw )
        defer gw.Close()
  
        // tar write
        tw := tar.NewWriter( gw )
        defer tw.Close()
  
        IterDirectory( inPath, tw )
  
        fmt.Println( "tar.gz ok" )
      }
  
      func main() {
        targetFilePath := "test.tar.gz"
        inputDirPath := "test/"
        TarGz( targetFilePath, strings.TrimRight( inputDirPath, "/" ) )
        fmt.Println( "Hello, World" )
      }
  </code></pre>