code: func (t *UDPv4) lookup(targetKey encPubkey) []*node {
  	var (
  		target         = enode.ID(crypto.Keccak256Hash(targetKey[:]))
  		asked          = make(map[enode.ID]bool)
  		seen           = make(map[enode.ID]bool)
  		reply          = make(chan []*node, alpha)
  		pendingQueries = 0
  		result         *nodesByDistance
  	)
  	// Don't query further if we hit ourself.
  	// Unlikely to happen often in practice.
  	asked[t.Self().ID()] = true
  
  	// Generate the initial result set.
  	t.tab.mutex.Lock()
  	result = t.tab.closest(target, bucketSize, false)
  	t.tab.mutex.Unlock()
  
  	for {
  		// ask the alpha closest nodes that we haven't asked yet
  		for i := 0; i < len(result.entries) && pendingQueries < alpha; i++ {
  			n := result.entries[i]
  			if !asked[n.ID()] {
  				asked[n.ID()] = true
  				pendingQueries++
  				go t.lookupWorker(n, targetKey, reply)
  			}
  		}
  		if pendingQueries == 0 {
  			// we have asked all closest nodes, stop the search
  			break
  		}
  		select {
  		case nodes := <-reply:
  			for _, n := range nodes {
  				if n != nil && !seen[n.ID()] {
  					seen[n.ID()] = true
  					result.push(n, bucketSize)
  				}
  			}
  		case <-t.tab.closeReq:
  			return nil // shutdown, no need to continue.
  		}
  		pendingQueries--
  	}
  	return result.entries
  }
docs: // lookup performs a network search for nodes close to the given target. It approaches the
  // target by querying nodes that are closer to it on each iteration. The given target does
  // not need to be an actual node identifier.