code: func (tab *Table) ReadRandomNodes(buf []*enode.Node) (n int) {
  	if !tab.isInitDone() {
  		return 0
  	}
  	tab.mutex.Lock()
  	defer tab.mutex.Unlock()
  
  	// Find all non-empty buckets and get a fresh slice of their entries.
  	var buckets [][]*node
  	for _, b := range &tab.buckets {
  		if len(b.entries) > 0 {
  			buckets = append(buckets, b.entries)
  		}
  	}
  	if len(buckets) == 0 {
  		return 0
  	}
  	// Shuffle the buckets.
  	for i := len(buckets) - 1; i > 0; i-- {
  		j := tab.rand.Intn(len(buckets))
  		buckets[i], buckets[j] = buckets[j], buckets[i]
  	}
  	// Move head of each bucket into buf, removing buckets that become empty.
  	var i, j int
  	for ; i < len(buf); i, j = i+1, (j+1)%len(buckets) {
  		b := buckets[j]
  		buf[i] = unwrapNode(b[0])
  		buckets[j] = b[1:]
  		if len(b) == 1 {
  			buckets = append(buckets[:j], buckets[j+1:]...)
  		}
  		if len(buckets) == 0 {
  			break
  		}
  	}
  	return i + 1
  }
docs: // ReadRandomNodes fills the given slice with random nodes from the table. The results
  // are guaranteed to be unique for a single invocation, no node will appear twice.