func getName(key, prefix string) (string, string, bool) {
	key = strings.TrimPrefix(key, prefix)
	parts := strings.Split(key, "/")
	if len(parts) == 0 {
		return "", "", false
	}
	if len(parts[0]) == 0 {
		parts = parts[1:]
	}
	if len(parts) < 2 {
		return "", "", false
	}
	return parts[0], parts[1], true
}
getName returns the domain and name
it returns false if there's an issue
the key is a path of /prefix/domain/name/id e.g /micro/registry/domain/service/uuid
package etcd
import (
	"context"
	"crypto/tls"
	"encoding/json"
	"errors"
	"net"
	"path"
	"sort"
	"strings"
	"sync"
	"time"
	"go.etcd.io/etcd/clientv3"
	"go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
	"go.etcd.io/etcd/mvcc/mvccpb"
	"github.com/micro/micro/v3/service/logger"
	"github.com/micro/micro/v3/service/registry"
	hash "github.com/mitchellh/hashstructure"
	"go.uber.org/zap"
)
const (
	prefix        = "/micro/registry/"
	defaultDomain = "micro"
)
type etcdRegistry struct {
	client  *clientv3.Client
	options registry.Options
	sync.RWMutex
	register map[string]register
	leases   map[string]leases
}
type register map[string]uint64
type leases map[string]clientv3.LeaseID
func NewRegistry(opts ...registry.Option) registry.Registry {
	e := &etcdRegistry{
		options:  registry.Options{},
		register: make(map[string]register),
		leases:   make(map[string]leases),
	}
	configure(e, opts...)
	return e
}
func newClient(e *etcdRegistry) (*clientv3.Client, error) {
	config := clientv3.Config{
		Endpoints: []string{"127.0.0.1:2379"},
	}
	if e.options.Timeout == 0 {
		e.options.Timeout = 5 * time.Second
	}
	if e.options.Secure || e.options.TLSConfig != nil {
		tlsConfig := e.options.TLSConfig
		if tlsConfig == nil {
			tlsConfig = &tls.Config{
				InsecureSkipVerify: true,
			}
		}
		config.TLS = tlsConfig
	}
	if e.options.Context != nil {
		u, ok := e.options.Context.Value(authKey{}).(*authCreds)
		if ok {
			config.Username = u.Username
			config.Password = u.Password
		}
		cfg, ok := e.options.Context.Value(logConfigKey{}).(*zap.Config)
		if ok && cfg != nil {
			config.LogConfig = cfg
		}
	}
	var cAddrs []string
	for _, address := range e.options.Addrs {
		if len(address) == 0 {
			continue
		}
		addr, port, err := net.SplitHostPort(address)
		if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" {
			port = "2379"
			addr = address
			cAddrs = append(cAddrs, net.JoinHostPort(addr, port))
		} else if err == nil {
			cAddrs = append(cAddrs, net.JoinHostPort(addr, port))
		}
	}
	if len(cAddrs) > 0 {
		config.Endpoints = cAddrs
	}
	if config.TLS != nil {
		for i, ep := range config.Endpoints {
			if !strings.HasPrefix(ep, "https://") {
				config.Endpoints[i] = "https://" + ep
			}
		}
	}
	cli, err := clientv3.New(config)
	if err != nil {
		return nil, err
	}
	return cli, nil
}
func configure(e *etcdRegistry, opts ...registry.Option) error {
	for _, o := range opts {
		o(&e.options)
	}
	cli, err := newClient(e)
	if err != nil {
		return err
	}
	if e.client != nil {
		e.client.Close()
	}
	e.client = cli
	return nil
}