1

Problem

I wish to add variable to the request context in a Middleware

fmt.Println(variable) // => map[key1:some text key2:[str1] key3:1234567890]

Then, access value.keyx in my Route handler

v := variable[key1]
fmt.Prinln(v) // => some text

// AnotherFunction requires a `string`
AnotherFunction(v)

Middleware

I add this variable to a context in a middleware such as:

// Middleware function
...
fmt.Println(variable) // => map[key1:some text key2:[str1] key3:1234567890]
fmt.Println(variable["key1"]) // => some text
ctx := context.WithValue(r.Context(), "var", variable)

which works fine.


Route Handler

Then, in my route handler I am able to access the context by doing

values := r.Context().Value("var")

fmt.Println(values) // => map[key1:some text key2:[str1] key3:1234567890]
fmt.Println(reflect.TypeOf(values)) // => map[string]interface {}

The issue is when I try to access the properties inside values


Attempts

  1. I tried the same I did in Middleware
fmt.Println(values["key1"]) // => invalid operation: cannot index claims (variable of type interface{})
  1. I investigated this solution but value is not a JSON object

  2. Doing a cast I am able to access "key1". BUT, it is not accepted by AnotherFunction(s string) which requires a string.

values := r.Context().Value("var")
casted := values.(map[string]interface{})

keyValue := casted["key1"]

fmt.Println(keyValue) // => some text
fmt.Println(reflect.TypeOf(keyValue)) // => string

// AnotherFunction requires a string input
AnotherFunction(keyValue) // => cannot use keyValue (variable of type interface{}) as string value in argument to AnotherFunction

So, I do another cast to work

values := r.Context().Value("var")
casted := values.(map[string]interface{})

keyValue := casted["key1"].(string) // <= Another cast

fmt.Println(keyValue) // => some text
fmt.Println(reflect.TypeOf(keyValue)) // => string

// AnotherFunction requires a string input
AnotherFunction(keyValue) // => OK

I'm convinced that there's another more correct way to do it.

3
  • 4
    "I'm convinced that there's another more correct way to do it." -- There isn't, not if you start out with the original type that you stored in the context. If you don't like doing so many type assertions then you should not be using map[string]interface{} to hold the data. Commented Jul 7, 2021 at 9:58
  • Thanks. The incoming variable map[string]interface{} (that is added in the context) is an output from a function that generates some fields dynamically. It would also be quite cumbersome to rearrange it otherwise. Commented Jul 7, 2021 at 11:29
  • You're exactly right Kmelow, cumbersome is what map[string]interface{} is. Often it is chosen out of convenience only for it to have the opposite effect down the road. Commented Jul 7, 2021 at 12:07

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.