加入收藏 | 设为首页 | 会员中心 | 我要投稿 南通站长网 (https://www.0513zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 运营中心 > 网站设计 > 教程 > 正文

优雅的读取http请求或响应的数据

发布时间:2019-02-02 09:10:33 所属栏目:教程 来源:戚银
导读:副标题#e# 从 http.Request.Body 或 http.Response.Body 中读取数据方法或许很多,标准库中大多数使用 ioutil.ReadAll 方法一次读取所有数据,如果是 json 格式的数据还可以使用 json.NewDecoder 从 io.Reader 创建一个解析器,假使使用 pprof 来分析程序总

使用 sync.Pool 的方式是不是有点怪,主要是 defer 和 api.pool.Put(buffer);buffer = nil 这里解释一下,为了提高 buufer 的复用率会在不使用时尽快把 buffer 放回到缓冲池中,defer 之所以会判断 buffer != nil 主要是在业务逻辑出现错误时,但是 buffer 还没有放回缓冲池时把 buffer 放回到缓冲池,因为在每个错误处理之后都写 api.pool.Put(buffer) 不是一个好的方法,而且容易忘记,但是如果在确定不再使用时 api.pool.Put(buffer);buffer = nil 就可以尽早把 buffer 放回到缓冲池中,提高复用率,减少新建 buffer。

这样就好了吗,别急,之前说服务里面还会构建请求,看看构建请求如何优化吧。

  1. package adapter 
  2.  
  3. import ( 
  4.     "bytes" 
  5.     "fmt" 
  6.     "io" 
  7.     "io/ioutil" 
  8.     "net/http" 
  9.     "sync" 
  10.  
  11.     "github.com/json-iterator/go" 
  12.     "github.com/sirupsen/logrus" 
  13.     "github.com/thinkeridea/go-extend/exbytes" 
  14.  
  15. type Adapter struct { 
  16.     pool sync.Pool 
  17.  
  18. func New() *Adapter { 
  19.     return &Adapter{ 
  20.         pool: sync.Pool{ 
  21.             New: func() interface{} { 
  22.                 return bytes.NewBuffer(make([]byte, 4096)) 
  23.             }, 
  24.         }, 
  25.     } 
  26.  
  27. func (api *Adapter) Request(r *Request) (*Response, error) { 
  28.     var err error 
  29.     buffer := api.pool.Get().(*bytes.Buffer) 
  30.     buffer.Reset() 
  31.     defer func() { 
  32.         if buffer != nil { 
  33.             api.pool.Put(buffer) 
  34.             buffer = nil 
  35.         } 
  36.     }() 
  37.  
  38.     e := jsoniter.NewEncoder(buffer) 
  39.     err = e.Encode(r) 
  40.     if err != nil { 
  41.         logrus.WithFields(logrus.Fields{ 
  42.             "request": r, 
  43.         }).Errorf("jsoniter.Marshal failure: %v", err) 
  44.         return nil, fmt.Errorf("jsoniter.Marshal failure: %v", err) 
  45.     } 
  46.  
  47.     data := buffer.Bytes() 
  48.     req, err := http.NewRequest("POST", "http://xxx.com", buffer) 
  49.     if err != nil { 
  50.         logrus.WithFields(logrus.Fields{ 
  51.             "data": exbytes.ToString(data), 
  52.         }).Errorf("http.NewRequest failed: %v", err) 
  53.         return nil, fmt.Errorf("http.NewRequest failed: %v", err) 
  54.     } 
  55.  
  56.     req.Header.Set("User-Agent", "xxx") 
  57.  
  58.     httpResponse, err := http.DefaultClient.Do(req) 
  59.     if httpResponse != nil { 
  60.         defer func() { 
  61.             io.Copy(ioutil.Discard, httpResponse.Body) 
  62.             httpResponse.Body.Close() 
  63.         }() 
  64.     } 
  65.  
  66.     if err != nil { 
  67.         logrus.WithFields(logrus.Fields{ 
  68.             "url": "http://xxx.com", 
  69.         }).Errorf("query service failed %v", err) 
  70.         return nil, fmt.Errorf("query service failed %v", err) 
  71.     } 
  72.  
  73.     if httpResponse.StatusCode != 200 { 
  74.         logrus.WithFields(logrus.Fields{ 
  75.             "url":         "http://xxx.com", 
  76.             "status":      httpResponse.Status, 
  77.             "status_code": httpResponse.StatusCode, 
  78.         }).Errorf("invalid http status code") 
  79.         return nil, fmt.Errorf("invalid http status code") 
  80.     } 
  81.  
  82.     buffer.Reset() 
  83.     _, err = io.Copy(buffer, httpResponse.Body) 
  84.     if err != nil { 
  85.         return nil, fmt.Errorf("adapter io.copy failure error:%v", err) 
  86.     } 
  87.  
  88.     respData := buffer.Bytes() 
  89.     logrus.WithFields(logrus.Fields{ 
  90.         "response_json": exbytes.ToString(respData), 
  91.     }).Debug("response json") 
  92.  
  93.     res := &Response{} 
  94.     err = jsoniter.Unmarshal(respData, res) 
  95.     if err != nil { 
  96.         logrus.WithFields(logrus.Fields{ 
  97.             "data": exbytes.ToString(respData), 
  98.             "url":  "http://xxx.com", 
  99.         }).Errorf("adapter jsoniter.Unmarshal failed, error:%v", err) 
  100.         return nil, fmt.Errorf("adapter jsoniter.Unmarshal failed, error:%v", err) 
  101.     } 
  102.      
  103.     api.pool.Put(buffer) 
  104.     buffer = nil 
  105.  
  106.     // ... 
  107.     return res, nil 

(编辑:南通站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读