func (r *BaseRegistry) providerRegistry(c *common.URL, params url.Values, f createPathFunc) (string, string, error) {
	var (
		dubboPath string
		rawURL    string
		err       error
	)
	if c.Path == "" || len(c.Methods) == 0 {
		return "", "", perrors.Errorf("conf{Path:%s, Methods:%s}", c.Path, c.Methods)
	}
	dubboPath = fmt.Sprintf("/dubbo/%s/%s", r.service(c), common.DubboNodes[common.PROVIDER])
	if f != nil {
		err = f(dubboPath)
	}
	if err != nil {
		logger.Errorf("facadeBasedRegistry.CreatePath(path{%s}) = error{%#v}", dubboPath, perrors.WithStack(err))
		return "", "", perrors.WithMessagef(err, "facadeBasedRegistry.CreatePath(path:%s)", dubboPath)
	}
	params.Add(constant.ANYHOST_KEY, "true")
	if len(c.Methods) != 0 {
		params.Add(constant.METHODS_KEY, strings.Join(c.Methods, ","))
	}
	logger.Debugf("provider url params:%#v", params)
	var host string
	if c.Ip == "" {
		host = localIP
	} else {
		host = c.Ip
	}
	host += ":" + c.Port
	for key, val := range params {
		if len(val) > 0 && val[0] == "" {
			params.Del(key)
		}
	}
	s, _ := url.QueryUnescape(params.Encode())
	rawURL = fmt.Sprintf("%s://%s%s?%s", c.Protocol, host, c.Path, s)
	dubboPath = fmt.Sprintf("/dubbo/%s/%s", r.service(c), (common.RoleType(common.PROVIDER)).String())
	logger.Debugf("provider path:%s, url:%s", dubboPath, rawURL)
	return dubboPath, rawURL, nil
}
providerRegistry for provider role do
package registry
import (
	"fmt"
	"net/url"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)
import (
	perrors "github.com/pkg/errors"
)
import (
	"dubbo.apache.org/dubbo-go/v3/common"
	"dubbo.apache.org/dubbo-go/v3/common/constant"
	"dubbo.apache.org/dubbo-go/v3/common/logger"
)
const (
	RegistryConnDelay = 3
	MaxWaitInterval = 3 * time.Second
)
var (
	processID = ""
	localIP   = ""
)
func init() {
	processID = fmt.Sprintf("%d", os.Getpid())
	localIP = common.GetLocalIp()
}
type createPathFunc func(dubboPath string) error
type FacadeBasedRegistry interface {
	Registry
	CreatePath(string) error
	DoRegister(string, string) error
	DoUnregister(string, string) error
	DoSubscribe(conf *common.URL) (Listener, error)
	DoUnsubscribe(conf *common.URL) (Listener, error)
	CloseAndNilClient()
	CloseListener()
	InitListeners()
}
type BaseRegistry struct {
	facadeBasedRegistry FacadeBasedRegistry
	*common.URL
	birth    int64           
	wg       sync.WaitGroup  
	done     chan struct{}
	cltLock  sync.RWMutex            
	services map[string]*common.URL  
}
func (r *BaseRegistry) InitBaseRegistry(url *common.URL, facadeRegistry FacadeBasedRegistry) Registry {
	r.URL = url
	r.birth = time.Now().UnixNano()
	r.done = make(chan struct{})
	r.services = make(map[string]*common.URL)
	r.facadeBasedRegistry = facadeRegistry
	return r
}
func (r *BaseRegistry) GetURL() *common.URL {
	return r.URL
}
func (r *BaseRegistry) Destroy() {
	r.facadeBasedRegistry.CloseListener()
	close(r.Done())
	r.WaitGroup().Wait()
	r.closeRegisters()
}
func (r *BaseRegistry) Register(conf *common.URL) error {
	var (
		ok  bool
		err error
	)
	if ipToRegistry := os.Getenv("DUBBO_IP_TO_REGISTRY"); ipToRegistry != "" {
		conf.Ip = ipToRegistry
	}
	if portToRegistry := os.Getenv("DUBBO_PORT_TO_REGISTRY"); portToRegistry != "" {
		conf.Port = portToRegistry
	}
	role, _ := strconv.Atoi(conf.GetParam(constant.ROLE_KEY, ""))
	r.cltLock.Lock()
	_, ok = r.services[conf.Key()]
	r.cltLock.Unlock()
	if ok {
		return perrors.Errorf("Path{%s} has been registered", conf.Key())
	}
	err = r.register(conf)
	if err != nil {
		return perrors.WithMessagef(err, "register(conf:%+v)", conf)
	}
	r.cltLock.Lock()
	r.services[conf.Key()] = conf
	r.cltLock.Unlock()
	logger.Debugf("(%sRegistry)Register(conf{%#v})", common.DubboRole[role], conf)
	return nil
}
func (r *BaseRegistry) UnRegister(conf *common.URL) error {
	var (
		ok     bool
		err    error
		oldURL *common.URL
	)
	func() {
		r.cltLock.Lock()
		defer r.cltLock.Unlock()
		oldURL, ok = r.services[conf.Key()]
		if !ok {
			err = perrors.Errorf("Path{%s} has not registered", conf.Key())
		}
		delete(r.services, conf.Key())
	}()
	if err != nil {
		return err
	}
	err = r.unregister(conf)
	if err != nil {
		func() {
			r.cltLock.Lock()
			defer r.cltLock.Unlock()
			r.services[conf.Key()] = oldURL
		}()
		return perrors.WithMessagef(err, "register(conf:%+v)", conf)
	}
	return nil
}
func (r *BaseRegistry) service(c *common.URL) string {
	return url.QueryEscape(c.Service())
}
func (r *BaseRegistry) RestartCallBack() bool {
	services := make([]*common.URL, 0, len(r.services))
	for _, confIf := range r.services {
		services = append(services, confIf)
	}
	flag := true
	for _, confIf := range services {
		err := r.register(confIf)
		if err != nil {
			logger.Errorf("(ZkProviderRegistry)register(conf{%#v}) = error{%#v}",
				confIf, perrors.WithStack(err))
			flag = false
			break
		}
		logger.Infof("success to re-register service :%v", confIf.Key())
	}
	if flag {
		r.facadeBasedRegistry.InitListeners()
	}
	return flag
}
func (r *BaseRegistry) register(c *common.URL) error {
	return r.processURL(c, r.facadeBasedRegistry.DoRegister, r.createPath)
}
func (r *BaseRegistry) unregister(c *common.URL) error {
	return r.processURL(c, r.facadeBasedRegistry.DoUnregister, nil)
}
func (r *BaseRegistry) processURL(c *common.URL, f func(string, string) error, cpf createPathFunc) error {
	if f == nil {
		panic(" Must provide a `function(string, string) error` to process URL. ")
	}
	var (
		err error
		params     url.Values
		rawURL     string
		encodedURL string
		dubboPath  string
	)
	params = url.Values{}
	c.RangeParams(func(key, value string) bool {
		params.Add(key, value)
		return true
	})
	params.Add("pid", processID)
	params.Add("ip", localIP)
	role, _ := strconv.Atoi(c.GetParam(constant.ROLE_KEY, ""))
	switch role {
	case common.PROVIDER:
		dubboPath, rawURL, err = r.providerRegistry(c, params, cpf)
	case common.CONSUMER:
		dubboPath, rawURL, err = r.consumerRegistry(c, params, cpf)
	default:
		return perrors.Errorf("@c{%v} type is not referencer or provider", c)
	}
	if err != nil {
		return perrors.WithMessagef(err, "@c{%v} registry fail", c)
	}
	encodedURL = url.QueryEscape(rawURL)
	dubboPath = strings.ReplaceAll(dubboPath, "$", "%24")
	err = f(dubboPath, encodedURL)
	if err != nil {
		return perrors.WithMessagef(err, "register Node(path:%s, url:%s)", dubboPath, rawURL)
	}
	return nil
}
func (r *BaseRegistry) createPath(dubboPath string) error {
	r.cltLock.Lock()
	defer r.cltLock.Unlock()
	return r.facadeBasedRegistry.CreatePath(dubboPath)
}