package client import ( "context" "net" "time" "google.golang.org/grpc" ) type Option func(*cfg) type cfg struct { addr string conn net.Conn gRPC cfgGRPC dialTimeout time.Duration } type cfgGRPC struct { dialOpts []grpc.DialOption conn *grpc.ClientConn } const defaultDialTimeout = 5 * time.Second func defaultCfg() *cfg { return &cfg{ gRPC: cfgGRPC{ dialOpts: []grpc.DialOption{ grpc.WithInsecure(), }, }, dialTimeout: defaultDialTimeout, } } func NewGRPCClientConn(opts ...Option) (*grpc.ClientConn, error) { cfg := defaultCfg() for i := range opts { opts[i](cfg) } var err error if cfg.gRPC.conn == nil { if cfg.conn != nil { if cfg.addr == "" { cfg.addr = cfg.conn.RemoteAddr().String() } cfg.gRPC.dialOpts = append(cfg.gRPC.dialOpts, grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { return cfg.conn, nil }), ) } dialCtx, cancel := context.WithTimeout(context.Background(), cfg.dialTimeout) cfg.gRPC.conn, err = grpc.DialContext(dialCtx, cfg.addr, cfg.gRPC.dialOpts...) cancel() if err != nil { return nil, err } } return cfg.gRPC.conn, err } func WithNetworkAddress(v string) Option { return func(c *cfg) { if v != "" { c.addr = v } } } func WithNetConn(v net.Conn) Option { return func(c *cfg) { if v != nil { c.conn = v } } } func WithDialTimeout(v time.Duration) Option { return func(c *cfg) { if v > 0 { c.dialTimeout = v } } } func WithGRPCDialOpts(v []grpc.DialOption) Option { return func(c *cfg) { if len(v) > 0 { c.gRPC.dialOpts = v } } } func WithGRPCConn(v *grpc.ClientConn) Option { return func(c *cfg) { if v != nil { c.gRPC.conn = v } } }