I understand that Go's lack of return value covariance makes adding WithContext to UniversalClient difficult even though all three client implementations support it.
I'm just wondering if there's a recommended workaround for those of us that want the flexibility of the universal interface but still need context for logging/instrumentation reasons?
FYI, my current workaround:
var (
contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
universalClientType = reflect.TypeOf((*UniversalClient)(nil)).Elem()
)
func WithContext(ctx context.Context, uc UniversalClient) UniversalClient {
switch uc := uc.(type) {
case *Client:
return uc.WithContext(ctx)
case *ClusterClient:
return uc.WithContext(ctx)
case *Ring:
return uc.WithContext(ctx)
case interface{ WithContext(context.Context) UniversalClient }:
return uc.WithContext(ctx)
default:
if fn := reflect.ValueOf(uc).MethodByName("WithContext"); fn.IsValid() {
fnType := fn.Type()
if fnType.NumIn() == 1 && fnType.NumOut() == 1 &&
fnType.In(0).Implements(contextType) &&
fnType.Out(0).Implements(universalClientType) {
args := []reflect.Value{reflect.ValueOf(ctx)}
return fn.Call(args)[0].Interface().(UniversalClient)
}
}
panic("not supported")
}
}
I am not aware of any good workarounds - my intention is to change go-redis and pass context.Context as first argument in v8. This way WithContext becomes less important but you will have to always pass context.Context.
Most helpful comment
I am not aware of any good workarounds - my intention is to change go-redis and pass
context.Contextas first argument in v8. This wayWithContextbecomes less important but you will have to always passcontext.Context.