code: func (m *Memberlist) setProbeChannels(seqNo uint32, ackCh chan ackMessage, nackCh chan struct{}, timeout time.Duration) {
  	// Create handler functions for acks and nacks
  	ackFn := func(payload []byte, timestamp time.Time) {
  		select {
  		case ackCh <- ackMessage{true, payload, timestamp}:
  		default:
  		}
  	}
  	nackFn := func() {
  		select {
  		case nackCh <- struct{}{}:
  		default:
  		}
  	}
  
  	// Add the handlers
  	ah := &ackHandler{ackFn, nackFn, nil}
  	m.ackLock.Lock()
  	m.ackHandlers[seqNo] = ah
  	m.ackLock.Unlock()
  
  	// Setup a reaping routing
  	ah.timer = time.AfterFunc(timeout, func() {
  		m.ackLock.Lock()
  		delete(m.ackHandlers, seqNo)
  		m.ackLock.Unlock()
  		select {
  		case ackCh <- ackMessage{false, nil, time.Now()}:
  		default:
  		}
  	})
  }
docs: // setProbeChannels is used to attach the ackCh to receive a message when an ack
  // with a given sequence number is received. The `complete` field of the message
  // will be false on timeout. Any nack messages will cause an empty struct to be
  // passed to the nackCh, which can be nil if not needed.