code: func (m *Memberlist) Leave(timeout time.Duration) error {
  	m.leaveLock.Lock()
  	defer m.leaveLock.Unlock()
  
  	if m.hasShutdown() {
  		panic("leave after shutdown")
  	}
  
  	if !m.hasLeft() {
  		atomic.StoreInt32(&m.leave, 1)
  
  		m.nodeLock.Lock()
  		state, ok := m.nodeMap[m.config.Name]
  		m.nodeLock.Unlock()
  		if !ok {
  			m.logger.Printf("[WARN] memberlist: Leave but we're not in the node map.")
  			return nil
  		}
  
  		d := dead{
  			Incarnation: state.Incarnation,
  			Node:        state.Name,
  		}
  		m.deadNode(&d)
  
  		// Block until the broadcast goes out
  		if m.anyAlive() {
  			var timeoutCh <-chan time.Time
  			if timeout > 0 {
  				timeoutCh = time.After(timeout)
  			}
  			select {
  			case <-m.leaveBroadcast:
  			case <-timeoutCh:
  				return fmt.Errorf("timeout waiting for leave broadcast")
  			}
  		}
  	}
  
  	return nil
  }
docs: // Leave will broadcast a leave message but will not shutdown the background
  // listeners, meaning the node will continue participating in gossip and state
  // updates.
  //
  // This will block until the leave message is successfully broadcasted to
  // a member of the cluster, if any exist or until a specified timeout
  // is reached.
  //
  // This method is safe to call multiple times, but must not be called
  // after the cluster is already shut down.