用golang解压缩gzip字符串

I have a string which contains a gzip compressed string, therefore there's no file headers, standard compress/gzip library throws error gzip: invalid header

How can I decompress a gzip compressed string in go?

This is what I'm trying

nbody := "eNorTk0uSi0BAAjRAoc="
rdata := strings.NewReader(nbody)
r,err := gzip.NewReader(rdata)
log.Println(r)
if err != nil {
    log.Fatal(err)
}
s, _ := ioutil.ReadAll(r)
fmt.Println(string(s))

... I have a string which contains a gzip compressed string

nbody := "eNorTk0uSi0BAAjRAoc="

This is not a "gzip compressed string". This looks like some base64 encoded data which need to be decoded first. After decoding it is not gzip either but zlib - which is basically the same as gzip (content compressed with deflate algorithm) but with a different file header. Therefore trying to decode it with gzip will not work.

The following will therefore take your original string, decode it from base64 and decompress it using zlib (not gzip):

package main

import (
        "bytes"
        "compress/zlib"
        "encoding/base64"
        "fmt"
        "io/ioutil"
)

func main() {
        b64z := "eNorTk0uSi0BAAjRAoc="
        z, _ := base64.StdEncoding.DecodeString(b64z)
        r, _ := zlib.NewReader(bytes.NewReader(z))
        result, _ := ioutil.ReadAll(r)
        fmt.Println(string(result))  // results in "secret"
}

If you have large inputs, you might want to use streams and a custom chain of decoders instead.

It has the advantage that (except for this example) neither the encoded input nor the decoded output has to reside in RAM.

package main

import (
    "bytes"
    "compress/zlib"
    "encoding/base64"
    "fmt"
    "io"
    "log"
    "os"
    "strings"
)

const nbody = "eNorTk0uSi0BAAjRAoc="

func main() {

    _, err := io.Copy(os.Stdout, decoder(strings.NewReader(nbody)))
    if err != nil {
        log.Fatalf("Error copying decoded value to stdout: %s",err)
    }
}

// This could use any io.Reader as input, for example
// a request body in http requests
func decoder(r io.Reader) io.Reader {

    // We simply set up a custom chain of Decoders
    d, err := zlib.NewReader(
        base64.NewDecoder(base64.StdEncoding, r))

    // This should only occur if one of the Decoders can not reset
    // its internal buffer. Hence, it validates a panic.
    if err != nil {
        panic(fmt.Sprintf("Error setting up decoder chain: %s", err))
    }

    // We return an io.Reader which can be used as any other
    return d

}

Run on playground