code: func (d *Dispatcher) AddService(serviceName string, service interface{}) {
  	if serviceName == "" {
  		logPanic("gorpc.Dispatcher: serviceName cannot be empty")
  	}
  	if _, ok := d.serviceMap[serviceName]; ok {
  		logPanic("gorpc.Dispatcher: service with name=[%s] has been already registered", serviceName)
  	}
  
  	funcMap := make(map[string]*funcData)
  
  	st := reflect.TypeOf(service)
  	if st.Kind() == reflect.Struct {
  		logPanic("gorpc.Dispatcher: service [%s] must be a pointer to struct, i.e. *%s", serviceName, st)
  	}
  
  	for i := 0; i < st.NumMethod(); i++ {
  		mv := st.Method(i)
  
  		if mv.PkgPath != "" {
  			// skip unexported methods
  			continue
  		}
  
  		funcName := serviceName + "." + mv.Name
  		fd := &funcData{
  			fv: mv.Func,
  		}
  		var err error
  		if fd.inNum, fd.reqt, err = validateFunc(funcName, fd.fv, true); err != nil {
  			logPanic("gorpc.Dispatcher: %s", err)
  		}
  		funcMap[mv.Name] = fd
  	}
  
  	if len(funcMap) == 0 {
  		logPanic("gorpc.Dispatcher: the service %s has no methods suitable for rpc", serviceName)
  	}
  
  	d.serviceMap[serviceName] = &serviceData{
  		sv:      reflect.ValueOf(service),
  		funcMap: funcMap,
  	}
  }
docs: // AddService registers public methods of the given service under
  // the given name serviceName.
  //
  // Since only public methods are registered, the service must have at least
  // one public method.
  //
  // All public methods must conform requirements described in AddFunc().