主页

索引

模块索引

搜索页面

3.10.1. 函数作为参数的使用技巧

在client-go中有这么一段代码,有人提 issue 问出这个疑问:

func (r *Request) Do(ctx context.Context) Result {
  var result Result
  err := r.request(ctx, func(req *http.Request, resp *http.Response) {
    result = r.transformResponse(resp, req)
  })
  if err != nil {
    return Result{err: err}
  }
  return result
}


func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Response)) error {
...
    resp, err := client.Do(req)
...
    fn(req, resp)
    return true
}

问题: 为什么Do要用传入 fn 的形式 去转换 Response, 直接按照下面的写不行么, 例如:

func (r *Request) Do(ctx context.Context) Result {
  result, err := r.request(ctx)
        if err != nil {
    return Result{err: err}
  }
  return result
}

func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Response)) (Result, error) {
...
    resp, err := client.Do(req)
...
   result = r.transformResponse(resp, req)
   return result, nil
}

里面lianghao208的回答特别好:

我个人认为这样写可以将request方法和fn解耦
比如这里的Do方法中的fn为transformResponse,
  是clientSet将apiserver返回的资源对象反序列化成kubernetes的资源对象数据结构的方法实现,
而下面的DoRaw方法的transformUnstructuredResponseError又是另一种fn的实现,
  我们可以还可以自己实现fn对clientSet进行封装,这样可重用性会更好。

DoRaw函数:

func (r *Request) DoRaw() ([]byte, error) {
  err := r.request(func(req *http.Request, resp *http.Response) {
    ...
    result.body, result.err = ioutil.ReadAll(resp.Body)
    glogBody("Response Body", result.body)
    if resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent {
      result.err = r.transformUnstructuredResponseError(resp, req, result.body)
    }
  })
  ...
  return result.body, result.err
}

主页

索引

模块索引

搜索页面