code: func (c *Client) ReadBlob(handle, offset uint16) ([]byte, error) {
  
  	// Acquire and reuse the txBuf, and release it after usage.
  	txBuf := <-c.chTxBuf
  	defer func() { c.chTxBuf <- txBuf }()
  
  	req := ReadBlobRequest(txBuf[:5])
  	req.SetAttributeOpcode()
  	req.SetAttributeHandle(handle)
  	req.SetValueOffset(offset)
  
  	b, err := c.sendReq(req)
  	if err != nil {
  		return nil, err
  	}
  
  	// Convert and validate the response.
  	rsp := ReadBlobResponse(b)
  	switch {
  	case rsp[0] == ErrorResponseCode && len(rsp) == 5:
  		return nil, ble.ATTError(rsp[4])
  	case rsp[0] == ErrorResponseCode && len(rsp) != 5:
  		fallthrough
  	case rsp[0] != rsp.AttributeOpcode():
  		fallthrough
  	case len(rsp) < 1:
  		return nil, ErrInvalidResponse
  	}
  	return rsp.PartAttributeValue(), nil
  }
docs: // ReadBlob requests the server to read part of the value of an attribute at a
  // given offset and return a specific part of the value in a Read Blob Response.
  // [Vol 3, Part F, 3.4.4.5 & 3.4.4.6]