亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

gzip 壓縮到 http responseWriter

gzip 壓縮到 http responseWriter

Go
牧羊人nacy 2022-03-03 15:07:22
我是 Go 新手。但是我在玩 REST Api。在我擁有的兩個函數中,我無法從 json.Marshal 中獲得與 json.Encoder 相同的行為我想用這個函數壓縮我的回復:func gzipFast(a *[]byte) []byte {    var b bytes.Buffer    gz := gzip.NewWriter(&b)    defer gz.Close()    if _, err := gz.Write(*a); err != nil {        panic(err)    }    return b.Bytes()}但是這個函數返回這個:curl http://localhost:8081/compressedget --compressed --verbose*   Trying 127.0.0.1...* Connected to localhost (127.0.0.1) port 8081 (#0)> GET /compressedget HTTP/1.1> Host: localhost:8081> User-Agent: curl/7.47.0> Accept: */*> Accept-Encoding: deflate, gzip> < HTTP/1.1 200 OK< Content-Encoding: gzip< Content-Type: application/json< Date: Wed, 24 Aug 2016 00:59:38 GMT< Content-Length: 30< * Connection #0 to host localhost left intact這是go函數:func CompressedGet(w http.ResponseWriter, r *http.Request, ps  httprouter.Params) {    box := Box{Width: 10, Height: 20, Color: "gree", Open: false}    box.ars = make([]int, 100)    for i := range box.ars {        box.ars[i] = i    }    //fmt.Println(r.Header.Get("Content-Encoding"))    w.Header().Set("Content-Type", "application/json")    w.Header().Set("Content-Encoding", "gzip")    b, _ := json.Marshal(box)    //fmt.Println(len(b))    //fmt.Println(len(gzipFast(&b)))    fmt.Fprint(w, gzipFast(&b))    //fmt.Println(len(gzipSlow(b)))    //gz := gzip.NewWriter(w)    //defer gz.Close()    //json.NewEncoder(gz).Encode(box)    r.Body.Close()}但是當我取消評論時://gz := gzip.NewWriter(w)//defer gz.Close()//json.NewEncoder(gz).Encode(box)它工作正常。
查看完整描述

3 回答

?
心有法竹

TA貢獻1866條經驗 獲得超5個贊

您需要在訪問底層字節之前刷新或關閉您的 gzip 編寫器,例如


func gzipFast(a *[]byte) []byte {

    var b bytes.Buffer

    gz := gzip.NewWriter(&b)

    if _, err := gz.Write(*a); err != nil {

        gz.Close()

        panic(err)

    }

    gz.Close()

    return b.Bytes()

}

否則,gzip writer 中的緩沖區,但尚未寫入最終流的內容不會被收集起來。


查看完整回答
反對 回復 2022-03-03
?
鳳凰求蠱

TA貢獻1825條經驗 獲得超4個贊

我認為問題在于使用fmt.Fprint(w, gzipFast(&b)).


如果您查看 gzipFast 的定義,它會返回一個[]byte. 您正在將此切片放入 print 函數中,該函數將所有內容“打印”到w.


如果你看一下 io.Writer 的定義:


type Writer interface {

        Write(p []byte) (n int, err error) }

您會看到作者可以將其[]byte作為輸入進行處理。


而不是fmt.Fprint(w, gzipFast(&b))你應該使用w.Write(gzipFast(&b)). 然后你不需要取消注釋:


//gz := gzip.NewWriter(w)

//defer gz.Close()

//json.NewEncoder(gz).Encode(box)

一切都是一個小例子,它顯示了代碼中發生的事情:


https://play.golang.org/p/6rzqLWTGiI


查看完整回答
反對 回復 2022-03-03
?
holdtom

TA貢獻1805條經驗 獲得超10個贊

我會避免[]byte手動壓縮。您可以輕松地使用標準庫中現有的編寫器。另外,看看compress/flate我認為應該使用哪個而不是 gzip。


package main


import (

    "net/http"

    "encoding/json"

    "compress/gzip"

    "log"

)


type Box struct {

    Width int `json:"width"`

}


func writeJsonResponseCompressed(w http.ResponseWriter, r *http.Request) {


    box := &Box{Width: 10}


    w.Header().Set("Content-Type", "application/json")

    w.Header().Set("Content-Encoding", "gzip")


    body, err := json.Marshal(box)

    if err != nil {

        // Your error handling

        return

    }


    writer, err := gzip.NewWriterLevel(w, gzip.BestCompression)

    if err != nil {

        // Your error handling

        return

    }


    defer writer.Close()


    writer.Write(body)

}


func main() {

    http.HandleFunc("/compressedget", writeJsonResponseCompressed)

    log.Fatal(http.ListenAndServe(":8081", nil))

}


查看完整回答
反對 回復 2022-03-03
  • 3 回答
  • 0 關注
  • 187 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號