package micro import ( "context" "fmt" "sync" "git.nspix.com/golang/micro/gateway/rpc" "git.nspix.com/golang/micro/registry" ) type Client struct { selector *registry.Selector clients sync.Map once sync.Once } func (c *Client) Do(ctx context.Context, r *Request) (resp Response, err error) { var ( ok bool node *registry.ServiceNode value interface{} client *rpc.Client ) value, ok = c.clients.Load(r.ServiceName) if ok { client = value.(*rpc.Client) goto _EXEC } if node, err = c.selector.Select(ctx, r.ServiceName); err != nil { err = fmt.Errorf("selector %s failed (%s)", r.ServiceName, err.Error()) return } client = rpc.NewClient() if err = client.DialerContext(ctx, "tcp", fmt.Sprintf("%s:%d", node.Address, node.Port)); err != nil { return } c.clients.Store(r.ServiceName, client) _EXEC: if resp, err = client.Do(ctx, rpc.NewRequest(r.Method, r.Body)); err != nil { client.Close() c.clients.Delete(r.ServiceName) } return } func (c *Client) Close() (err error) { c.clients.Range(func(key, value interface{}) bool { client := value.(*rpc.Client) _ = client.Close() c.clients.Delete(key) return true }) return } func NewClient(reg registry.Registry) *Client { return &Client{ selector: registry.NewSelector(reg), } }