public function go($dir = null)
    {
        // set up the output directory
        if (null === $dir) {
            $dir = rtrim(sys_get_temp_dir(), '\\/')
                . DIRECTORY_SEPARATOR
                . 'pharextract'
                . DIRECTORY_SEPARATOR
                . basename($this->file, '.phar');
        } else {
            $dir = realpath($dir);
        }

        // skip if already extracted
        $md5 = $dir . DIRECTORY_SEPARATOR . md5_file($this->file);

        if (file_exists($md5)) {
            return $dir;
        }

        if (!is_dir($dir)) {
            $this->createDir($dir);
        }

        // open the file and skip stub
        $this->open();

        if (-1 === fseek($this->handle, $this->stub)) {
            throw new RuntimeException(
                sprintf(
                    'Could not seek to %d in the file "%s".',
                    $this->stub,
                    $this->file
                )
            );
        }

        // read the manifest
        $info = $this->readManifest();

        if ($info['flags'] & self::GZ) {
            if (!function_exists('gzinflate')) {
                throw new RuntimeException(
                    'The zlib extension is (gzinflate()) is required for "%s.',
                    $this->file
                );
            }
        }

        if ($info['flags'] & self::BZ2) {
            if (!function_exists('bzdecompress')) {
                throw new RuntimeException(
                    'The bzip2 extension (bzdecompress()) is required for "%s".',
                    $this->file
                );
            }
        }

        self::purge($dir);
        $this->createDir($dir);
        $this->createFile($md5);

        foreach ($info['files'] as $info) {
            $path = $dir . DIRECTORY_SEPARATOR . $info['path'];
            $parent = dirname($path);

            if (!is_dir($parent)) {
                $this->createDir($parent);
            }

            if (preg_match('{/$}', $info['path'])) {
                $this->createDir($path, 0777, false);
            } else {
                $this->createFile(
                    $path,
                    $this->extractFile($info)
                );
            }
        }

        return $dir;
    }