code: func getIDs(snap *raftpb.Snapshot, ents []raftpb.Entry) []uint64 {
  	ids := make(map[uint64]struct{})
  	if snap != nil {
  		for _, id := range snap.Metadata.ConfState.Nodes {
  			ids[id] = struct{}{}
  		}
  	}
  	for _, e := range ents {
  		if e.Type != raftpb.EntryConfChange {
  			continue
  		}
  		if snap != nil && e.Index < snap.Metadata.Index {
  			continue
  		}
  		var cc raftpb.ConfChange
  		if err := cc.Unmarshal(e.Data); err != nil {
  			log.L.WithError(err).Panic("unmarshal configuration change should never fail")
  		}
  		switch cc.Type {
  		case raftpb.ConfChangeAddNode:
  			ids[cc.NodeID] = struct{}{}
  		case raftpb.ConfChangeRemoveNode:
  			delete(ids, cc.NodeID)
  		case raftpb.ConfChangeUpdateNode:
  			// do nothing
  		default:
  			log.L.Panic("ConfChange Type should be either ConfChangeAddNode, or ConfChangeRemoveNode, or ConfChangeUpdateNode!")
  		}
  	}
  	var sids []uint64
  	for id := range ids {
  		sids = append(sids, id)
  	}
  	return sids
  }
docs: // getIDs returns an ordered set of IDs included in the given snapshot and
  // the entries. The given snapshot/entries can contain two kinds of
  // ID-related entry:
  // - ConfChangeAddNode, in which case the contained ID will be added into the set.
  // - ConfChangeRemoveNode, in which case the contained ID will be removed from the set.