code: func (p *Processor) Unmarshal(data []byte) (interface{}, error) {
  	var m map[string]json.RawMessage
  	err := json.Unmarshal(data, &m)
  	if err != nil {
  		return nil, err
  	}
  	if len(m) != 1 {
  		return nil, errors.New("invalid json data")
  	}
  
  	for msgID, data := range m {
  		i, ok := p.msgInfo[msgID]
  		if !ok {
  			return nil, fmt.Errorf("message %v not registered", msgID)
  		}
  
  		// msg
  		if i.msgRawHandler != nil {
  			return MsgRaw{msgID, data}, nil
  		} else {
  			msg := reflect.New(i.msgType.Elem()).Interface()
  			return msg, json.Unmarshal(data, msg)
  		}
  	}
  
  	panic("bug")
  }
docs: // goroutine safe