code: func (m *Memberlist) sendPingAndWaitForAck(addr string, ping ping, deadline time.Time) (bool, error) {
  	conn, err := m.transport.DialTimeout(addr, deadline.Sub(time.Now()))
  	if err != nil {
  		// If the node is actually dead we expect this to fail, so we
  		// shouldn't spam the logs with it. After this point, errors
  		// with the connection are real, unexpected errors and should
  		// get propagated up.
  		return false, nil
  	}
  	defer conn.Close()
  	conn.SetDeadline(deadline)
  
  	out, err := encode(pingMsg, &ping)
  	if err != nil {
  		return false, err
  	}
  
  	if err = m.rawSendMsgStream(conn, out.Bytes()); err != nil {
  		return false, err
  	}
  
  	msgType, _, dec, err := m.readStream(conn)
  	if err != nil {
  		return false, err
  	}
  
  	if msgType != ackRespMsg {
  		return false, fmt.Errorf("Unexpected msgType (%d) from ping %s", msgType, LogConn(conn))
  	}
  
  	var ack ackResp
  	if err = dec.Decode(&ack); err != nil {
  		return false, err
  	}
  
  	if ack.SeqNo != ping.SeqNo {
  		return false, fmt.Errorf("Sequence number from ack (%d) doesn't match ping (%d)", ack.SeqNo, ping.SeqNo)
  	}
  
  	return true, nil
  }
docs: // sendPingAndWaitForAck makes a stream connection to the given address, sends
  // a ping, and waits for an ack. All of this is done as a series of blocking
  // operations, given the deadline. The bool return parameter is true if we
  // we able to round trip a ping to the other node.