code: func (p *Processor) Route(msg interface{}, userData interface{}) error {
  	// raw
  	if msgRaw, ok := msg.(MsgRaw); ok {
  		i, ok := p.msgInfo[msgRaw.msgID]
  		if !ok {
  			return fmt.Errorf("message %v not registered", msgRaw.msgID)
  		}
  		if i.msgRawHandler != nil {
  			i.msgRawHandler([]interface{}{msgRaw.msgID, msgRaw.msgRawData, userData})
  		}
  		return nil
  	}
  
  	// json
  	msgType := reflect.TypeOf(msg)
  	if msgType == nil || msgType.Kind() != reflect.Ptr {
  		return errors.New("json message pointer required")
  	}
  	msgID := msgType.Elem().Name()
  	i, ok := p.msgInfo[msgID]
  	if !ok {
  		return fmt.Errorf("message %v not registered", msgID)
  	}
  	if i.msgHandler != nil {
  		i.msgHandler([]interface{}{msg, userData})
  	}
  	if i.msgRouter != nil {
  		i.msgRouter.Go(msgType, msg, userData)
  	}
  	return nil
  }
docs: // goroutine safe