code: func (b *EtcdBackend) GetRange(ctx context.Context, startKey, endKey []byte, limit int) (*backend.GetResult, error) {
  	if len(startKey) == 0 {
  		return nil, trace.BadParameter("missing parameter startKey")
  	}
  	if len(endKey) == 0 {
  		return nil, trace.BadParameter("missing parameter endKey")
  	}
  	opts := []clientv3.OpOption{clientv3.WithSerializable(), clientv3.WithRange(prependPrefix(endKey))}
  	if limit > 0 {
  		opts = append(opts, clientv3.WithLimit(int64(limit)))
  	}
  	start := b.clock.Now()
  	re, err := b.client.Get(ctx, prependPrefix(startKey), opts...)
  	batchReadLatencies.Observe(time.Since(start).Seconds())
  	batchReadRequests.Inc()
  	if err := convertErr(err); err != nil {
  		return nil, trace.Wrap(err)
  	}
  	items := make([]backend.Item, 0, len(re.Kvs))
  	for _, kv := range re.Kvs {
  		value, err := unmarshal(kv.Value)
  		if err != nil {
  			return nil, trace.Wrap(err)
  		}
  		items = append(items, backend.Item{
  			Key:     trimPrefix(kv.Key),
  			Value:   value,
  			ID:      kv.ModRevision,
  			LeaseID: kv.Lease,
  		})
  	}
  	sort.Sort(backend.Items(items))
  	return &backend.GetResult{Items: items}, nil
  }
docs: // GetRange returns query range