Fix "should not use basic type string as key in context.WithValue" golint
I achieve the above by doing the following and feel it's pretty clean
package util
import "context"
type contextKey string
func (c contextKey) String() string {
return string(c)
}
var (
// ContextKeyDeleteCaller var
ContextKeyDeleteCaller = contextKey("deleteCaller")
// ContextKeyJobID var
ContextKeyJobID contextKey
)
// GetCallerFromContext gets the caller value from the context.
func GetCallerFromContext(ctx context.Context) (string, bool) {
caller, ok := ctx.Value(ContextKeyDeleteCaller).(string)
return caller, ok
}
// GetJobIDFromContext gets the jobID value from the context.
func GetJobIDFromContext(ctx context.Context) (string, bool) {
jobID, ok := ctx.Value(ContextKeyJobID).(string)
return jobID, ok
}
..and then set on context by,
ctx := context.WithValue(context.Background(), util.ContextKeyDeleteCaller, "Kafka Listener")
..get value from context by,
caller, ok := util.GetCallerFromContext(ctx)
if !ok {
dc.log.Warn("could not get caller from context")
}
fmt.Println("value is:", caller) // will be 'Kafka Listener'
and can print out value of key by doing,
fmt.Println("Key is:", ContextKeyDeleteCaller.String())
Just use a key type:
type key int
const (
keyPrincipalID key = iota
// ...
)
Since you've defined a separate type, it will never collide. Even if you have two packages, pkg1.key(0) != pkg2.key(0)
.
See also: Go Blog about key collisions in context.
Use type struct{}
much better.
type ctxKey struct{} // or exported to use outside the package
ctx = context.WithValue(ctx, ctxKey{}, 123)
fmt.Println(ctx.Value(ctxKey{}).(int) == 123) // true
Reference: https://golang.org/pkg/context/#WithValue
The provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys. To avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables' static type should be a pointer or interface.