I am trying to write a csv parser using the example provided here. It works great for all native types but I am having trouble with any structs that contain a timestamp of type time.Time. It exits with an error of "cannot convert this type".
This is the code.
//For each field in a given struct...
//Get a field
val := sv.Field(i)
// this is necessary because Kind can't tell
// distinguish between a primitive type
// and a type derived from it. We're looking
// for a Value interface defined on
// the pointer to this value
_, ok := val.Addr().Interface().(Value)
if ok {
val = val.Addr()
kind = value_k
} else {
switch Kind {
case reflect.Int, reflect.Int16, reflect.Int8,
reflect.Int32, reflect.Int64:
kind = int_k
case reflect.Uint, reflect.Uint16, reflect.Uint8,
reflect.Uint32, reflect.Uint64:
kind = uint_k
case reflect.Float32, reflect.Float64:
kind = float_k
case reflect.String:
kind = string_k
default:
// Kind is Struct here
kind = value_k
_, ok := val.Interface().(Value)
if !ok {
err = os.NewError("cannot convert this type ")
this = nil
return
}
}
}
What this code does is take an interface and a reader. It attempts to match the field headers in the reader (csv file) with field names in the interface. It also reflects on the interface (struct) and collects positional a type information for later setting the fields in the iterator. It is this step that is failing for non-native types.
I've tried a few methods to work around this but the only thing that seems to work is changing the timestamp to a string. I am undoubtedly missing something and would greatly appreciate some guidance.
Related
I want to find out why
x:= odsMap[segRef]
x.GetValue("#OriginDestinationKey")
works, but this does not:
odsMap[segRef].GetValue("#OriginDestinationKey")
?
The last snippet prints the following errors:
cannot call pointer method on odsMap[segRef]go
cannot take the address of odsMap[segRef]
These errors happen during compilation time (not runtime). So, my main question is why I need an intermediate variable x to access the function?
Regarding the type of the variables odsMap is a map[string] XMLElement and segRef is a string.
Thanks.
Map index expressions are not addressable, because the internals of a map may change when a new entry is added to it, so the spec intentionally does not allow taking its address (this gives greater freedom for map implementations).
This means if you store non-pointers in the map, and you want to call a method of a stored value that has a pointer receiver, that would require to take the address of the non-pointer value (to be used as the receiver), but since map index expressions are not addressable, that results in a compile-time error.
A workaround is to store pointer values in the map, so there is no need to take the address of an index expression, because it's already a pointer. An example of this can be seen in this answer: Why should constructor of Go return address? If we have this type:
type My int
func (m *My) Str() string { return strconv.Itoa(int(*m)) }
This gives the compile-time error in question:
m := map[int]My{0: My(12)}
m[0].Str() // Error!
But this works:
m := map[int]*My{}
my := My(12)
m[0] = &my // Store a pointer in the map
m[0].Str() // You can call it, no need to take the address of m[0]
// as it is already a pointer
Another option is to assign it to a local variable whose address can be taken, and call the pointer method on that. Care must be taken though, as if the method has pointer receiver, it might modify pointed object or its components (e.g. fields of a struct), which would not be reflected in the value stored in the map. If you go down this path, you might have to reassign the value to the key in the map to have the updated value.
All-in-all, if you have a value whose type has methods with pointer receiver, you're better off using it (store, pass) as a pointer and not as a non-pointer value.
See related questions:
Pointer methods on non pointer types
How can I store reference to the result of an operation in Go?
#icza's answer is the correct one.
Here is an example to illustrate how "value receiver" vs "pointer receiver" interact with "pointer map" vs "values map" :
https://play.golang.org/p/JVp6DirgPkU
package main
import (
"fmt"
)
// a simple type, with two methods : one with a value receiver, one with a pointer receiver
type Item struct {
name string
}
func (i Item) GetNameByValue() string {
return i.name
}
func (i *Item) GetNameByRef() string {
return i.name
}
func main() {
{
// in this map, we store *pointers* to Item values
mapByRef := make(map[int]*Item)
mapByRef[0] = &Item{"I am stored as a pointer"}
// GetNameByRef will work on a *Item : "mapByRef[0]" is already a pointer
fmt.Println("GetByRef :", mapByRef[0].GetNameByRef())
// GetNameByValue will work on a *Item : go automatically turns this into '(*mapByRef[0]).GetNameByValue()', and this is valid
fmt.Println("GetByValue :", mapByRef[0].GetNameByValue())
}
{
// in this map, we store Item values (no pointers)
mapByValue := make(map[int]Item)
mapByValue[0] = Item{"I am stored as a value"}
// GetNameByValue will work on a Item : "mapByValue[0]" has the right type
fmt.Println("GetByValue :", mapByValue[0].GetNameByValue())
// GetNameByRef will not work : go tries to turn this into : (&mapByValue[0]).GetNameByRef(),
// and go refuses to let you take the address of a value inside a map
// fmt.Println("GetByRef :", mapByValue[0].GetNameByRef())
// compiler error :
// ./prog.go:47:46: cannot call pointer method on mapByValue[0]
// ./prog.go:47:46: cannot take the address of mapByValue[0]
// you will need some way to copy the value before taking its address :
item := mapByValue[0]
fmt.Println("item.GetByRef :", item.GetNameByRef())
// same as :
fmt.Println("(&item).GetByRef :", (&item).GetNameByRef())
}
}
// Output :
//
// GetByRef : I am stored as a pointer
// GetByValue : I am stored as a pointer
// GetByValue : I am stored as a value
// item.GetByRef : I am stored as a value
// (&item).GetByRef : I am stored as a value
I have a map of type set, which is actually a map[string]string. However, passing it to a function which accepts a map[string]string fails, because Go does not recognize set as one.
However, I fail to convince the compiler it is one. Is there any way to resolve this, without looping and copying?
package main
import (
"fmt"
)
type name string
type field string
type set map[name]field // map[string]string after all
type plain map[string]string // also map[string]string
func main() {
var typed = set{"hi": "ho"} // map[string]string?
back := plain(typed) // cannot convert typed (type set) to type plain
back := typed.(plain) // invalid type assertion: typed.(plain) (non-interface type set on left)
echo(back)
}
func echo(in map[string]string) {
fmt.Println(in)
}
You could do this using the unsafe package.
Note: I don't think this would necessarily be a good idea, and probably the right way would be to just iterate and copy, but since it does answer the question asked...
var typed = set{"hi": "ho"} // map[string]string?
p := unsafe.Pointer(&typed)
var back plain
back = *(*plain)(p)
Playground: https://play.golang.org/p/yienSuJSnQU
I have managed to do this, but it does not look efficient:
var t reflect.Type
switch t {
case reflect.TypeOf(([]uint8)(nil)):
// handle []uint8 array type
}
First question, are you sure you want to switch on reflect.Type and not use a type switch? Example:
switch x := y.(type) {
case []uint8:
// x is now a []uint8
}
Assuming that will not work for your situation, my recommendation is to make those package variables. Example:
var uint8SliceType = reflect.TypeOf(([]uint8)(nil))
func Foo() {
var t reflect.Type
switch t {
case uint8SliceType:
// handle []uint8 array type
}
}
you may not need reflect if you are just trying to detect type.
switch t := myVar.(type){
case []uint8:
// t is []uint8
case *Foo:
// t is *Foo
default:
panic("unknown type")
}
What are you actually trying to accomplish?
The answer to the initial question How to switch on reflect.Type? is: You can’t. However, you can do it with reflect.Value.
Given a variable v interface{} you can call reflect.TypeOf(v) and reflect.ValueOf(v), which return a reflect.Type or reflect.Value, resp.
If the type of v is not interface{} then these function calls will convert it to interface{}.
reflect.Type contains various run-time information about the type, but it does not contain anything usable to retrieve the type of v itself as needed in a type switch.
Hovewer, reflect.Value provides it through its Interface() method, which returns the underlying value as interface{}. This you can use in a type switch or type assertion.
import "fmt"
import "reflect"
var v int
var rt reflect.Type = reflect.TypeOf(v)
fmt.Println(rt.String(), " has awesome properties: Its alignment is",
rt.Align(), ", it has", rt.Size(), "bytes, is it even comparable?",
rt.Comparable())
// … but reflect.Type won’t tell us what the real type is :(
// Let’s see if reflect.Value can help us.
var rv reflect.Value = reflect.ValueOf(v)
// Here we go:
vi := rv.Interface()
switch vi.(type) {
// Mission accomplished.
}
Perhaps it helps to clarify a few points which may cause confusion about dynamic typing in Go. At least I was confused by this for quite some time.
reflect vs. interface{}
In Go there are two systems of run-time generics:
In the language: interface{}, useful for type switches/assertions,
In the library: The reflect package, useful for inspection of run-time generic types and values of such.
These two systems are separated worlds, and things that are possible with one are impossible with the other. For example, Given an interface{}, it is in plain Go (with safe code) impossible to, say, if the value is an array or slice, regardless of its element type, then get the value of the i-th element. One needs to use reflect in order to do that. Conversely, with reflect it is impossible to make a type switch or assertion: convert it to interface{}, then you can do that.
There are only very few points of an interface between these systems. In one direction it is the TypeOf() and ValueOf() functions which accept interface{} and return a reflect struct. In the other direction it is Value.Interface().
It is a bit counter-intuitive that one needs a Value, not a Type, to do a type switch. At least this is somewhat consistent with the fact that one needs a value construct a Type by calling TypeOf().
reflect.Kind
Both reflect.Type and reflect.Value have a Kind() method. Some suggest using the value these methods return, of type reflect.Kind, to imitate a type switch.
While this may be useful in certain situations, it is not a replacement for a type switch. For example, using Kind one cannot distinguish between int64 and time.Duration because the latter is defined as
type Duration int64
Kind is useful to tell if a type is any kind of struct, array, slice etc., regardless of the types it is composed of. This is not possible to find out with a type switch.
(Side note. I had the same question and found no answer here helpful so I went to figure it out myself. The repeated counter-question “why are you doing this?”, followed by unrelated answers did not help me either. I have a good reason why I want to do it precisely this way.)
This might work.
switch t := reflect.TypeOf(a).String() {
case "[]uint8":
default:
}
As others have said, it's not clear what you are trying to achieve by switching on reflect.Type However, I came across this question when probably trying to do something similar, so I will give you my solution in case it answers your question.
As captncraig said, a simple type switch could be done on a interface{} variable without needing to use reflect.
func TypeSwitch(val interface{}) {
switch val.(type) {
case int:
fmt.Println("int with value", val)
case string:
fmt.Println("string with value ", val)
case []uint8:
fmt.Println("Slice of uint8 with value", val)
default:
fmt.Println("Unhandled", "with value", val)
}
}
However, going beyond this, the usefulness of reflection in the context of the original question could be in a function that accepts a struct with arbitrarily typed fields, and then uses a type switch to process the field according to its type. It is not necessary to switch directly on reflect.Type, as the type can be extracted by reflect and then a standard type switch will work. For example:
type test struct {
I int
S string
Us []uint8
}
func (t *test) SetIndexedField(index int, value interface{}) {
e := reflect.ValueOf(t).Elem()
p := e.Field(index)
v := p.Interface()
typeOfF := e.Field(index).Type()
switch v.(type) {
case int:
p.SetInt(int64(value.(int)))
case string:
p.SetString(value.(string))
case []uint8:
p.SetBytes(value.([]uint8))
default:
fmt.Println("Unsupported", typeOfF, v, value)
}
}
The following examples demonstrate the use of this function:
var t = test{10, "test string", []uint8 {1, 2, 3, 4}}
fmt.Println(t)
(&t).SetIndexedField(0, 5)
(&t).SetIndexedField(1, "new string")
(&t).SetIndexedField(2, []uint8 {8, 9})
fmt.Println(t)
(A few points on reflection in go:
It is necessary to export the struct fields for reflect to be able to use them, hence the capitalisation of the field names
In order to modify the field values, it would be necessary to use a pointer to the struct as in this example function
Elem() is used to "dereference" the pointer in reflect
)
Well, I did this by first transfer it to interface and then use the.(type)
ty := reflect.TypeOf(*c)
vl := reflect.ValueOf(*c)
for i:=0;i<ty.NumField();i++{
switch vl.Field(i).Interface().(type) {
case string:
fmt.Printf("Type: %s Value: %s \n",ty.Field(i).Name,vl.Field(i).String())
case int:
fmt.Printf("Type: %s Value: %d \n",ty.Field(i).Name,vl.Field(i).Int())
}
}
So I found some code that help me get started with reflection in Go (golang), but I'm having trouble getting a the underlying value so that I can basically create a map[string]string from a struct and it's fields.
Eventually, I'd like to make the result into a map[string]interface{}, but this one issue is kind of blocking me.
The code I have at the moment:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
FirstName string `tag_name:"tag 1"`
LastName string `tag_name:"tag 2"`
Age int `tag_name:"tag 3"`
}
func inspect(f interface{}) map[string]string {
m := make(map[string]string)
val := reflect.ValueOf(f).Elem()
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)
f := valueField.Interface()
val := reflect.ValueOf(f)
m[typeField.Name] = val.String()
}
return m
}
func dump(m map[string]string) {
for k, v := range m {
fmt.Printf("%s : %s\n", k, v)
}
}
func main() {
f := &Foo{
FirstName: "Drew",
LastName: "Olson",
Age: 30,
}
a := inspect(f)
dump(a)
}
The output from running the code:
FirstName : Drew
LastName : Olson
Age : <int Value>
From what I understand the output for FirstName and LastName are actual reflect.Value objects but for strings the String() method on value just outputs the underlying String. I'd like to either get the int and change it into a string, but from the relfect package documentation I'm not immediately seeing how that's done.
Soo.... How do I get the underlying value from a reflect.Value in golang?
A good example of how to parse values is the fmt package. See this code.
Using the mentioned code to match your problem would look like this:
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
m[typeField.Name] = strconv.FormatInt(val.Int(), 10)
case reflect.String:
m[typeField.Name] = val.String()
// etc...
}
Basically you need to check for all available Kinds.
It looks like you're on the right track. The problem I see with your code is it makes assumptions about the values, meaning when do you call Elem() and how many times (to resolve pointers). In order to know this you need to look at the reflect.Kind. Is the value a reflect.Ptr? Then use Elem().
Once you have the value from val.Interface() / val.String() / val.Int() you can convert your values as needed. What you use is going to depend on reflect.Kind. To convert an int to/from string you need to use the strconv package.
The encoding/json and encoding/xml packages do this kind of work already. The source code provides some great examples. For example, take a look at copyValue in encoding/xml/read.go and marshalSimple in encoding/xml/marshal.go.
This should be easier to do with Go 1.5 (August 2015)
See review 8731 and commit 049b89d by Rob Pike (robpike):
fmt: treat reflect.Value specially - as the value it holds
This would allow you to print the actual value of a Reflect.Value() argument:
When a reflect.Value is passed to Printf (etc.), fmt called the String method, which does not disclose its contents.
To get the contents, one could call Value.Interface(), but that is illegal
if the Value is not exported or otherwise forbidden.
This CL improves the situation with a trivial change to the fmt package: when we see a reflect.Value as an argument, we treat it exactly as we treat a reflect.Value we make inside the package.
This means that we always print the contents of the Value as if that was the argument to Printf.
This is arguably a breaking change but I think it is a genuine improvement and no greater a break than many other tweaks we have made to formatted output from this package.
Another simple solution can be ,
flavorName = fmt.Sprintf("%v",strct)
" fmt.Sprintf() " will return the value which can be stored in a variable.
I'm currently getting desperate over the behaviour of golangs reflect package, which to me doesn't seem consistent at all.
1) As far as I understand it, a reflect.Value seems to carry a pointer to the underlying value.
E.g. if I call
var s string
v1 := reflect.ValueOf(&s).Elem()
v2 := v1
v2.SetString("Hello World!")
fmt.Println(s)
It prints me "Hello World!".
However, this doesn't seem to hold true for a reflect.Value obtained by a call to Field().
val := ... //Assign a reflect.Value to it
nextval := val.Field(0) //Make sure that Field exists and is of type map
nextval = reflect.MakeMap(reflect.MapOf(KEY, ELEM))
nextval.SetMapIndex(Some_value_of_type_KEY, Something_of_type_ELEM)
fmt.Println(nextval.MapKeys()
fmt.Println(val.Field(index).MapKeys())
This prints
[Some_value_of_type_KEY]
[]
which is a major annoyance. Anyone knows why this is the case?
===================================================
2) Consider the function
func Test(v interface{}) {
val := reflect.ValueOf(v)
if val.Kind() != reflect.Struct {
fmt.Println("It is a struct")
}
}
If I call it with any struct as an argument it prints "This is a struct".
However, I won't be able to assign new values to stuff inside v by using val,
due to the value not being addressable. Working around by the following:
func Test(v interface{}) {
val := reflect.ValueOf(&v).Elem()
if val.Kind() != reflect.Struct {
fmt.Println("This never get's printed!")
}
}
According to the doc, I would assume, that by taking the '&' I use a pointer to v and by the call of Elem() I get the element it points to, therefore val.Kind() should still return the same thing. It doesn't. val.Kind() now is a reflect.Interface.
Is there a way of not having to go
valForTestingKind := reflect.ValueOf(v)
valForSettingNewValue := reflect.ValueOf(&v).Elem()
as this somehow feels wrong.
Part 1:
By assigning to nextval, you are breaking its association with the original val. Instead, use the Set() method.
nextval.Set(reflect.MakeMap(reflect.MapOf(KEY, ELEM)))
Set() is the equivalent of assignment in the reflection world. Of course, you must make sure it is assignable using reflect.ValueOf(&v).Elem() as you do in your first code example.
Part 2:
The issue here is that you have another level of indirection. v is of type interface{} and has a concrete value whose type is of Kind struct. Just like with every function that accepts an interface typed parameter, when you call reflect.ValueOf, the parameter is automatically converted to that type. However, converting an interface to another interface results in the concrete value being reboxed in the new interface type. The information of the type before it was reboxed is lost. As an example, a function that accepts an io.Writer would not know that the calling function considered it an io.ReaderWriter.
In this context, it means that reflect.ValueOf cannot tell if you passed an os.File (some struct) or a file boxed in an interface{}. It assumes you passed an os.File and shows you the Kind "struct".
However, when you pass a pointer to an interface{}, you are passing an interface{} variable that can be modified. You are not passing the underlying concrete type and that has important consequences. You can .Set() anything, not just what the original concrete type allows. You also can't edit individual fields as anything in an interface{} is not assignable. If the concrete type is in fact a pointer, you can do a fourth dereference (.Elem()) and modify fields from there.
So, what does this mean in terms of code?
//let v = an interface{} with a concrete type of SomeStruct
val := reflect.ValueOf(&v).Elem()
fmt.Println(val.Elem().Kind()) // struct
val.Elem().Field(0).Set(10) // PANIC! Field isn't assignable.
val.Set("a string which is not a SomeStruct")
fmt.Println(val.Elem().Kind()) // string
I made an example here: http://play.golang.org/p/6MULn3KoNh
I want to talk about your second block of code:
val := ... //Assign a reflect.Value to it
nextval := val.Field(0) //Make sure that Field exists and is of type map
nextval = reflect.MakeMap(reflect.MapOf(KEY, ELEM))
nextval.SetMapIndex(Some_value_of_type_KEY, Something_of_type_ELEM)
fmt.Println(nextval.MapKeys()
fmt.Println(val.Field(index).MapKeys())
On the third line, you are reassigning a new, different object to the variable nextval. Shouldn't you call some kind of setting method on nextval instead of reassigning it? In your first example, you called SetString but in this example you are just reassigning the variable and that might be why the behavior is different. After you reassign the variable, nextval will no longer be connected in any way to val.Field(0). Also, what is index?
If this does not explain your problem, please edit the question to contain a short, self-contained, correct, compilable example ( SSCCE ). I want to be able to post it into the text box on the front page of golang.org in order to see the problem. You should always post an SSCCE when possible.
You have not shown a complete and compilable code. Do you pass a pointer to a struct or do you pass the struct by value? In the later case reflection cannot mutate it.
Values stored in a map are not addressable even when not using reflection.
http://play.golang.org/p/wYLeJ3W4R2
http://play.golang.org/p/ttUGBVh1lc
https://groups.google.com/forum/#!topic/golang-nuts/jzjEXoc9FwU
https://groups.google.com/forum/#!topic/golang-nuts/V_5kwzwKJAY