code: func (rtm *RTM) ManageConnection() {
  	var (
  		err  error
  		info *Info
  		conn *websocket.Conn
  	)
  
  	for connectionCount := 0; ; connectionCount++ {
  		// start trying to connect
  		// the returned err is already passed onto the IncomingEvents channel
  		if info, conn, err = rtm.connect(connectionCount, rtm.useRTMStart); err != nil {
  			// when the connection is unsuccessful its fatal, and we need to bail out.
  			rtm.Debugf("Failed to connect with RTM on try %d: %s", connectionCount, err)
  			rtm.disconnect()
  			return
  		}
  
  		// lock to prevent data races with Disconnect particularly around isConnected
  		// and conn.
  		rtm.mu.Lock()
  		rtm.conn = conn
  		rtm.info = info
  		rtm.mu.Unlock()
  
  		rtm.IncomingEvents <- RTMEvent{"connected", &ConnectedEvent{
  			ConnectionCount: connectionCount,
  			Info:            info,
  		}}
  
  		rtm.Debugf("RTM connection succeeded on try %d", connectionCount)
  
  		// we're now connected so we can set up listeners
  		go rtm.handleIncomingEvents()
  
  		// this should be a blocking call until the connection has ended
  		rtm.handleEvents()
  
  		select {
  		case <-rtm.disconnected:
  			// after handle events returns we need to check if we're disconnected
  			return
  		default:
  			// otherwise continue and run the loop again to reconnect
  		}
  	}
  }
docs: // ManageConnection can be called on a Slack RTM instance returned by the
  // NewRTM method. It will connect to the slack RTM API and handle all incoming
  // and outgoing events. If a connection fails then it will attempt to reconnect
  // and will notify any listeners through an error event on the IncomingEvents
  // channel.
  //
  // If the connection ends and the disconnect was unintentional then this will
  // attempt to reconnect.
  //
  // This should only be called once per slack API! Otherwise expect undefined
  // behavior.
  //
  // The defined error events are located in websocket_internals.go.