Is there a way to list keys in context.Context? - go

So, I have a context.Context(https://golang.org/pkg/context/) variable with me, is there a way I can list all the keys this variable holds?

It is possible to list the internals of context.Context using unsafe reflection and using that information to figure out the keys and/or see if the information you want is in the context.
There are some pitfall such as if the context implementation returns a hardcoded value for a key it wont show up here, and it can be quite unclear on how to actually access the values using keys.
This is nothing I run in production. But in my case I needed to be able to inspect the context.Context to understand better what information it contains.
func printContextInternals(ctx interface{}, inner bool) {
contextValues := reflect.ValueOf(ctx).Elem()
contextKeys := reflect.TypeOf(ctx).Elem()
if !inner {
fmt.Printf("\nFields for %s.%s\n", contextKeys.PkgPath(), contextKeys.Name())
}
if contextKeys.Kind() == reflect.Struct {
for i := 0; i < contextValues.NumField(); i++ {
reflectValue := contextValues.Field(i)
reflectValue = reflect.NewAt(reflectValue.Type(), unsafe.Pointer(reflectValue.UnsafeAddr())).Elem()
reflectField := contextKeys.Field(i)
if reflectField.Name == "Context" {
printContextInternals(reflectValue.Interface(), true)
} else {
fmt.Printf("field name: %+v\n", reflectField.Name)
fmt.Printf("value: %+v\n", reflectValue.Interface())
}
}
} else {
fmt.Printf("context is empty (int)\n")
}
}
Examples:
func Ping(w http.ResponseWriter, r *http.Request) {
printContextInternals(r.Context(), false)
/* Prints
Fields for context.valueCtx
context is empty (int)
field name: key
value: net/http context value http-server
field name: val
value: &{Addr::20885 Handler:0xc00001c000 TLSConfig:0xc000001c80 ReadTimeout:0s ReadHeaderTimeout:0s WriteTimeout:0s IdleTimeout:0s MaxHeaderBytes:0 TLSNextProto:map[h2:0x12db010] ConnState:<nil> ErrorLog:<nil> BaseContext:<nil> ConnContext:<nil> disableKeepAlives:0 inShutdown:0 nextProtoOnce:{done:1 m:{state:0 sema:0}} nextProtoErr:<nil> mu:{state:0 sema:0} listeners:map[0xc00015a840:{}] activeConn:map[0xc000556fa0:{}] doneChan:<nil> onShutdown:[0x12e9670]}
field name: key
value: net/http context value local-addr
field name: val
value: [::1]:20885
field name: mu
value: {state:0 sema:0}
field name: done
value: 0xc00003c2a0
field name: children
value: map[context.Background.WithValue(type *http.contextKey, val <not Stringer>).WithValue(type *http.contextKey, val [::1]:20885).WithCancel.WithCancel:{}]
field name: err
value: <nil>
field name: mu
value: {state:0 sema:0}
field name: done
value: <nil>
field name: children
value: map[]
field name: err
value: <nil>
field name: key
value: 0
field name: val
value: map[]
field name: key
value: 1
field name: val
value: &{handler:0x151cf50 buildOnly:false name: err:<nil> namedRoutes:map[] routeConf:{useEncodedPath:false strictSlash:false skipClean:false regexp:{host:<nil> path:0xc0003d78f0 queries:[]} matchers:[0xc0003d78f0 [GET POST]] buildScheme: buildVarsFunc:<nil>}}
*/
printContextInternals(context.Background(), false)
/* Prints
Fields for context.emptyCtx
context is empty (int)
*/
}

No there is no way to list all the keys of context.Context. Because that type is just an interface. So what does this mean?
In general a variables can hold a concrete type or an interface. A variable with an interface type does not have any concrete type informations on it. So it would makes no difference if the interface is empty (interface{}) or context.Context. Because they could be a lot of different types which are implementing that interface. The variable does not have a concrete type. It is just something abstract.
If you use reflection you could observer the fields and all the methods of the type which is set to that variable (with interface type). But the logic how the method Value(key interface{}) interface{} is implemented is not fixed. It does not have to be a map. You could also make an implementation with slices, database, an own type of an hash table, ...
So there is no general way to list all the values.

Related

go when to use & or not?

I am confused whether to use a & with go when declaring a variable and init with a struct
say we have a struct wrapper
type HttpResult struct {
Status int32 `json:"status"`
Msg string `json:"msg"`
Data interface{} `json:"data,omitempty"`
}
and a struct defining the user model
type OmUser struct {
Id primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Name string `json:"name"`
Password string `json:"password"`
Email string `json:"email"`
}
And the following declaring seems give the same result:
myOmUser := OmUser{ //note no & sign here
Name: "Tony",
Password: "mypass",
Email: "tony#foo.com"
}
httpResult := &HttpResult{
Status: 0,
Msg: "ok",
Data: myOmUser,
}
js, _ := json.Marshal(httpResult)
fmt.Println(js)
Or
myOmUser := &OmUser{ //note the & sign
Name: "Tony",
Password: "mypass",
Email: "tony#foo.com"
}
httpResult := &HttpResult{
Status: 0,
Msg: "ok",
Data: myOmUser,
}
js, _ := json.Marshal(httpResult)
fmt.Println(js)
so, when to use & and why?
In your particular example it doesn't make a difference.
But when we look at an example of using json.Unmarshal() it makes a bit more sense:
jsonBlob := []byte(`{"id": "1", "name": "bob", "password": "pass", "email", "hi#me.com"}`)
var newOmUser OmUser
err := json.Unmarshal(jsonBlob, &newOmUser)
if err != nil {
panic(err)
}
Here we declare the variable before hand, and then we use the & to pass a pointer to that variable into the Unmarshal function.
That means that the Unmarshal function can reach out and update that variable, even though it's declared outside of the function.
Without the &, the Unmarshal function would get a copy of the newOmUser variable, and it would leave the original newOmUser variable that we declared empty.
When it comes to pointers, my general rule of thumb is:
Don't use them unless you have to.
If you need to use any unmarshalling functions, you'll need them. There are lots of other functions that make use of them.
Here's a quick exercise that helps me understand a little more about pointers:
func uppercase(s string) {
s = strings.ToUpper(s)
fmt.Println(s)
}
// Same as the uppercase() function, but works with a pointer.
func uppercasePointer(s *string) {
*s = strings.ToUpper(*s)
fmt.Println(*s)
}
name := "bob"
uppercase(name) // prints 'BOB'
fmt.Println(name) // prints 'bob' - our variable was not changed
name2 := "bobpointer"
uppercasePointer(&name2) // prints 'BOBPOINTER'
fmt.Println(name2) // prints 'BOBPOINTER' - our variable was changed
When we call the uppercase(name) function, go makes a copy of the name variable and sends it to the uppercase function.
Whatever the function does to that copy that it received stays in the function. The original variable that we declared outside the function is not changed.
When we call the uppercasePointer(&name2) function, we are sending a pointer to the name2 variable we declared.
The function can use that pointer to reach out and update the name2 variable that we declared earlier.
At first, you might not see the point of pointers, but as you continue to use go, you will see that they help us solve some complex problems.
Empty interface type in Go can hold values of any type. Tour here.
So in your HttpResult.Data is an empty interface type. So you can assigne any type to it.
The difference between defining a variable with & is getting a pointer of that type. Tour here.
Those are obviously two types with two different functionalities in Go. But you can assign both to empty interface type variable because its accepting values of any type.
package main
import (
"fmt"
"reflect"
)
type OmUser struct {
}
func main() {
myOmUser := OmUser{}
myOmUser2 := &OmUser{}
fmt.Println(reflect.TypeOf(myOmUser)) //main.OmUser
fmt.Println(reflect.TypeOf(myOmUser2)) //*main.OmUser
}
For more details about &, read Go doc address operators
For an
operand x of type T, the address operation &x generates a pointer of
type *T to x. The operand must be addressable, that is, either a
variable, pointer indirection, or slice indexing operation; or a field
selector of an addressable struct operand; or an array indexing
operation of an addressable array. As an exception to the
addressability requirement, x may also be a (possibly parenthesized)
composite literal. If the evaluation of x would cause a run-time
panic, then the evaluation of &x does too.
fooA := &Foo{}
fooA has type *Foo.
fooB := Foo{}
fooB has type Foo.
https://tour.golang.org/moretypes/1
In practice, this means if you had a func that accepted type *Foo you could do either of the following...
func someFunc(f *Foo) {
// ...
}
fooA := &Foo{}
someFunc(fooA)
fooB := Foo{}
someFunc(&fooB)
So realistically, create whichever you need to be honest.

Updating a key in a map, whilst iterating over that map

I want to update the key from one name to another using URL params. I have the code, but the output is incorrect. See below.
This is the map
var data map[string][]string
The PUT method for the function im calling
r.HandleFunc("/updatekey/{key}/{newkey}", handleUpdateKey).Methods("PUT")
The handleUpdateKey func, which is noted up explaining exactly what it's doing.
func handleUpdateKey(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
k := params["key"] //get url params
nk := params["newkey"]
s := make([]string, len(data[k])) //create slice of string to store map variables
for i := range data { //range over the data map
fmt.Fprintf(w, i)
if k != i { //check if no keys exist with URL key param
fmt.Fprintf(w, "That KEY doesn't exist in memory")
break //kill the loop
} else { //if there is a key the same as the key param
for _, values := range data[i] { //loop over the slice of string (values in that KEY)
s = append(s, values) //append all those items to the slice of string
}
delete(data, k) //delete the old key
for _, svalues := range s { //loop over the slice of string we created earlier
data[nk] = append(data[nk], svalues) //append the items within the slice of string, to the new key... replicating the old key, with a new key name
}
}
}
}
The below should assign all the values of that KEY to a slice of string, which we later iterate over and add to the new KEY. This works, however, the output is as below which is clearly incorrect
KEY: catt: VALUE:
KEY: catt: VALUE:
KEY: catt: VALUE: zeus
KEY: catt: VALUE: xena
OLD OUTPUT:
KEY: dog: VALUE: zeus
KEY: dog: VALUE: xena
CORRECT NEW OUTPUT:
KEY: catt: VALUE: zeus
KEY: catt: VALUE: xena
In most languages, altering a structure you're iterating over will cause strange things to happen. Particularly maps. You have to find another way.
Fortunately there's no need to iterate at all. Your loop is just one big if/else statement. If the key matches, do something. If it doesn't, do something else. Since this is a map, there's no need to search for the key using iteration, it can be looked up directly. There's also no need for all that laborious looping just to copy a map value.
if val, ok := data[k]; ok {
// Copy the value
data[nk] = val
// Delete the old key
delete(data, k)
} else {
fmt.Fprintf(w, "The key %v doesn't exist", k)
}
Finally, avoid using globals in functions. It makes it difficult to understand what effect a function has on the program if it can change globals. data should be passed in to the function to make it clear.
func handleUpdateKey(w http.ResponseWriter, r *http.Request, data map[string][]string)

How to use Go reflection pkg to get the type of a slice struct field?

I'm trying to use reflection to build a routine that will list the Name, Kind and Type of all fields in an arbitrary struct that gets passed in. Here is what I've got so far:
type StatusVal int
type Foo struct {
Name string
Age int
}
type Bar struct {
Status StatusVal
FSlice []Foo
}
func ListFields(a interface{}) {
v := reflect.ValueOf(a).Elem()
for j := 0; j < v.NumField(); j++ {
f := v.Field(j)
n := v.Type().Field(j).Name
t := f.Type().Name()
fmt.Printf("Name: %s Kind: %s Type: %s\n", n, f.Kind(), t)
}
}
func main() {
var x Bar
ListFields(&x)
}
The output is as follows:
Name: Status Kind: int Type: StatusVal
Name: FSlice Kind: slice Type:
When the field is a slice, the type is blank. I tried several ways to get the slice's data type, but all attempts resulted in a panic... usually this one:
reflect: call of reflect.Value.Elem on slice Value
What changes need to be made to this code so that the type for all fields, including slices, will be listed in the output?
Here's the playground link: https://play.golang.org/p/zpfrYkwvlZ
A slice type given in a type literal like []Foo is an unnamed type, hence Type.Name() returns an empty string "".
Use Type.String() instead:
t := f.Type().String()
And then the output (try it on the Go Playground):
Name: Status Kind: int Type: main.StatusVal
Name: FSlice Kind: slice Type: []main.Foo
See related question to know more about types and their names: Identify non builtin-types using reflect

How do I use reflect to check if the type of a struct field is interface{}?

I am using the reflect package to determine the type of a struct field is interface{}
I want to do the comparison like so (where t is a reflect.Type):
if t == reflect.TypeOf(interface{}) {
}
The problem is that the compiler complains: type interface {} is not an expression.
Is there anyway to check if the type of a struct field is an interface{}?
You can get the type of the interface Y by creating a nil instance and using reflection:
yType := reflect.TypeOf((*Y)(nil)).Elem()
and then use the expression
reflect.TypeOf(x).Implements(yType)
to check if the type implements the interface.
Interfaces themselves can not be instantiated. The interface{} interface which is the empty interface is implemented by all types so all fields implement that.
https://play.golang.org/p/gRfheIW_9Y
Actually it also works with the empty interface{} itself but this will always return true (if i'm not missing something):
https://play.golang.org/p/29rWP4LtIo
interface{} is a type, and reflect.TypeOf() expects a value. So you can't pass the literal interface{} to it. You can only pass a value.
Back to the original question. Let's see a struct example:
type My struct {
A int
B interface{}
C io.Reader
}
You want to tell if the type of a field is interface{}. Acquire the reflect.Type of the struct type, then you can access the fields using Type.Field() or Type.FieldByName().
This gives you a value of type reflect.StructField which stores the type of the field.
So far so good. But what should we compare it to? interface{} is an interface type with 0 methods. You can't have (instantiate) a value of that type. You can only have values of concrete types, but yes, they may be wrapped in an interface type.
You could use Type.Kind, and compare it to reflect.Interface, which tells you if it's an interface, but this is true for all interface types. You could also check if it has 0 methods with Type.NumMethod(), which must be 0 for interface{}, but other interfaces could also have 0 methods...
You may use Type.Name, but since interface{} is a unnamed type, its name is the empty string "" (and there are other unnamed types). You may use Type.String() which returns "interface {}" for the empty interface:
t := reflect.TypeOf(My{})
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
fmt.Printf("Field %q, type: %-12v, type name: %-8q, is interface{}: %v\n",
f.Name, f.Type,
f.Type.Name(),
f.Type.String() == "interface {}",
)
}
Output (try it on the Go Playground):
Field "A", type: int , type name: "int" , is interface{}: false
Field "B", type: interface {}, type name: "" , is interface{}: true
Field "C", type: io.Reader , type name: "Reader", is interface{}: false
You might find this related question interesting / useful: Identify non builtin-types using reflect

How to get a value from map

Problem
Fetching data from map
Data Format
res = map[Event_dtmReleaseDate:2009-09-15 00:00:00 +0000 +00:00 Trans_strGuestList:<nil> strID:TSTB]
Note
How to get the following value from the above result
Event_dtmReleaseDate
strID
Trans_strGuestList
What i tried:
res.Map("Event_dtmReleaseDate");
Error : res.Map undefined (type map[string]interface {} has no field or method Map)
res.Event_dtmReleaseDate;
Error: v.id undefined (type map[string]interface {} has no field or method id)
Your variable is a map[string]interface {} which means the key is a string but the value can be anything. In general the way to access this is:
mvVar := myMap[key].(VariableType)
Or in the case of a string value:
id := res["strID"].(string)
Note that this will panic if the type is not correct or the key does not exist in the map, but I suggest you read more about Go maps and type assertions.
Read about maps here: http://golang.org/doc/effective_go.html#maps
And about type assertions and interface conversions here: http://golang.org/doc/effective_go.html#interface_conversions
The safe way to do it without a chance to panic is something like this:
var id string
var ok bool
if x, found := res["strID"]; found {
if id, ok = x.(string); !ok {
//do whatever you want to handle errors - this means this wasn't a string
}
} else {
//handle error - the map didn't contain this key
}
In general to get value from map you have to do something like this:
package main
import "fmt"
func main() {
m := map[string]string{"foo": "bar"}
value, exists := m["foo"]
// In case when key is not present in map variable exists will be false.
fmt.Printf("key exists in map: %t, value: %v \n", exists, value)
}
Result will be:
key exists in map: true, value: bar

Resources