code: func (n *Node) SetAddr(ctx context.Context, addr string) error {
  	n.addrLock.Lock()
  	defer n.addrLock.Unlock()
  
  	n.opts.Addr = addr
  
  	if !n.IsMember() {
  		return nil
  	}
  
  	newRaftMember := &api.RaftMember{
  		RaftID: n.Config.ID,
  		NodeID: n.opts.ID,
  		Addr:   addr,
  	}
  	if err := n.cluster.UpdateMember(n.Config.ID, newRaftMember); err != nil {
  		return err
  	}
  
  	// If the raft node is running, submit a configuration change
  	// with the new address.
  
  	// TODO(aaronl): Currently, this node must be the leader to
  	// submit this configuration change. This works for the initial
  	// use cases (single-node cluster late binding ports, or calling
  	// SetAddr before joining a cluster). In the future, we may want
  	// to support having a follower proactively change its remote
  	// address.
  
  	leadershipCh, cancelWatch := n.SubscribeLeadership()
  	defer cancelWatch()
  
  	ctx, cancelCtx := n.WithContext(ctx)
  	defer cancelCtx()
  
  	isLeader := atomic.LoadUint32(&n.signalledLeadership) == 1
  	for !isLeader {
  		select {
  		case leadershipChange := <-leadershipCh:
  			if leadershipChange == IsLeader {
  				isLeader = true
  			}
  		case <-ctx.Done():
  			return ctx.Err()
  		}
  	}
  
  	return n.updateNodeBlocking(ctx, n.Config.ID, addr)
  }
docs: // SetAddr provides the raft node's address. This can be used in cases where
  // opts.Addr was not provided to NewNode, for example when a port was not bound
  // until after the raft node was created.