Reputation: 4158
My scan is not updating its destination variable. I sort of got it working with:
ValueName := reflect.New(reflect.ValueOf(value).Elem().Type())
But I don't think it is working the way I want.
func (self LightweightQuery) Execute(incrementedValue interface{}) {
existingObj := reflect.New(reflect.ValueOf(incrementedValue).Elem().Type())
if session, err := connection.GetRandomSession(); err != nil {
panic(err)
} else {
// buildSelect just generates a select query, I have test the query and it comes back with results.
query := session.Query(self.buildSelect(incrementedValue))
bindQuery := cqlr.BindQuery(query)
logger.Error("Existing obj ", existingObj)
for bindQuery.Scan(&existingObj) {
logger.Error("Existing obj ", existingObj)
....
}
}
}
Both log messages are the exact same Existing obj &{ 0 0 0 0 0 0 0 0 0 0 0 0}
(Spaces are string fields.) Is this because of the heavy use of reflection to generate a new object? In their docs it says I should use var ValueName type
to define my destination but I cannot seem to do that with reflection. I realize this may be silly, but maybe even just pointing me in the direction for further debugging this would be great. My skills with Go are quite lacking!
Upvotes: 1
Views: 264
Reputation: 417612
What is it you want exactly? Do you want to update a variable you pass to Execute()
?
If so, you have to pass a pointer to Execute()
. And then you only need to pass reflect.ValueOf(incrementedValue).Interface()
to Scan()
. This works because reflect.ValueOf(incrementedValue)
is a reflect.Value
holding an interface{}
(the type of your parameter) which holds a pointer (the pointer you pass to Execute()
), and Value.Interface()
will return a value of type interface{}
holding the pointer, the exact thing you have to pass Scan()
.
See this example (which uses fmt.Sscanf()
, but concept is the same):
func main() {
i := 0
Execute(&i)
fmt.Println(i)
}
func Execute(i interface{}) {
fmt.Sscanf("1", "%d", reflect.ValueOf(i).Interface())
}
It will print 1
from main()
, as the value 1
is set inside Execute()
.
If you don't want to update the variable passed to Execute()
, just create a new value with identical type, since you're using reflect.New()
which returns the Value
of a pointer, you have to pass existingObj.Interface()
which returns an interface{}
holding the pointer, the thing you want to pass to Scan()
. (What you did is you passed a pointer to a reflect.Value
to Scan()
which is not something Scan()
expects.)
Demonstration with fmt.Sscanf()
:
func main() {
i := 0
Execute2(&i)
}
func Execute2(i interface{}) {
o := reflect.New(reflect.ValueOf(i).Elem().Type())
fmt.Sscanf("2", "%d", o.Interface())
fmt.Println(o.Elem().Interface())
}
This will print 2
.
Another variant of Execute2()
is that if you call Interface()
right on the value returned by reflect.New()
:
func Execute3(i interface{}) {
o := reflect.New(reflect.ValueOf(i).Elem().Type()).Interface()
fmt.Sscanf("3", "%d", o)
fmt.Println(*(o.(*int))) // type assertion to extract pointer for printing purposes
}
This Execute3()
will print 3
as expected.
Try all examples on the Go Playground.
Upvotes: 1