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!
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.