Extracting files from .7z archives in Go

part of Go Cookbook
When I first needed to read a .7z archive from Go, I used the external 7z program. Today, github.com/bodgit/sevenzip provides a pure Go reader, so an external executable is no longer the only option.

Read an archive in pure Go

Add the dependency to your module:
go get github.com/bodgit/sevenzip
This complete program streams each regular file to stdout. It does not create files using archive-controlled paths or load each entire file into memory.
package main

import (
	"fmt"
	"io"
	"log"
	"os"

	"github.com/bodgit/sevenzip"
)

func readArchive(path string) error {
	archive, err := sevenzip.OpenReader(path)
	if err != nil {
		return err
	}
	defer archive.Close()

	for _, file := range archive.File {
		if !file.FileInfo().Mode().IsRegular() {
			continue
		}
		fmt.Fprintf(os.Stderr, "reading %s\n", file.Name)
		reader, err := file.Open()
		if err != nil {
			return err
		}
		_, copyErr := io.Copy(os.Stdout, reader)
		closeErr := reader.Close()
		if copyErr != nil {
			return copyErr
		}
		if closeErr != nil {
			return closeErr
		}
	}
	return nil
}

func main() {
	if err := readArchive("foo.7z"); err != nil {
		log.Fatal(err)
	}
}
Close each entry before moving on; deferring all entry closes until the end can retain resources unnecessarily. See the package documentation for supported compression methods, encrypted archives, and the io/fs interface.
For untrusted archives, impose limits on total decompressed bytes, entry count, and processing time. Streaming avoids a large output buffer, but does not by itself prevent decompression bombs. If you extract to disk, reject absolute paths and traversal components, and prevent symlinks from escaping the destination. Go’s os.Root, introduced in Go 1.24 and expanded in Go 1.25, provides operations confined to a directory tree.

Use the external 7-Zip program

My original lzmadec wrapper exposed an io.ReadCloser backed by a 7z child process. That was a practical workaround in 2015, but its old examples should not be used as current library installation instructions.
The same technique can still be implemented with exec.Cmd from os/exec: 7-Zip’s -so option sends decompressed data to stdout. Install the 7-Zip command-line tools, start the process, stream its stdout, and call Wait to check its exit status and release resources. Read stderr concurrently if using a separate pipe. If the caller stops reading early, cancel the process and still wait for it.
See Advanced command execution in Go for subprocess handling. Pure Go is simpler to deploy when the reader supports the archive’s compression and encryption methods.
#go #programming
Sep 5 2026

Related articles

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you: