扫描功能无法正常工作。

huangapple go评论89阅读模式
英文:

Scan not working

问题

我的扫描程序没有更新目标变量。我试过用以下代码部分解决:

ValueName := reflect.New(reflect.ValueOf(value).Elem().Type())

但我觉得它没有按照我想要的方式工作。

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只是生成一个select查询,我已经测试了查询,它返回了结果。
		query := session.Query(self.buildSelect(incrementedValue))
		bindQuery := cqlr.BindQuery(query)
		logger.Error("Existing obj ", existingObj)
		for bindQuery.Scan(&existingObj) {
			logger.Error("Existing obj ", existingObj)
            ....
        }
   }
}

两条日志信息完全相同 Existing obj &{ 0 0 0 0 0 0 0 0 0 0 0 0}(空格是字符串字段)。这是因为反射被大量使用来生成一个新对象吗?在文档中,他们说我应该使用 var ValueName type 来定义我的目标,但是我似乎无法通过反射来做到这一点。我意识到这可能很愚蠢,但是指点我进一步调试的方向可能会很有帮助。我在Go方面的技能非常欠缺!

英文:

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!

答案1

得分: 1

你想要的确切是什么?你想要更新传递给Execute()的变量吗?

如果是这样,你需要将指针传递给Execute()。然后,你只需要将reflect.ValueOf(incrementedValue).Interface()传递给Scan()。这样做的原因是reflect.ValueOf(incrementedValue)是一个持有interface{}(你参数的类型)的reflect.Value,它持有一个指针(你传递给Execute()的指针),而Value.Interface()将返回一个持有指针的interface{}类型的值,这正是你需要传递给Scan()的东西。

看看这个例子(使用fmt.Sscanf(),但概念是相同的):

func main() {
    i := 0
    Execute(&i)
    fmt.Println(i)
}

func Execute(i interface{}) {
    fmt.Sscanf("1", "%d", reflect.ValueOf(i).Interface())
}

它将从main()打印出1,因为值1Execute()内部设置。

如果你不想更新传递给Execute()的变量,只需创建一个具有相同类型的新值,因为你使用的是返回指针的reflect.New(),你必须传递existingObj.Interface(),它返回一个持有指针的interface{},这是你要传递给Scan()的东西。(你所做的是将指针传递给Scan()reflect.Value,而Scan()并不期望这样做。)

使用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())
}

这将打印出2

Execute2()的另一种变体是,如果你直接在reflect.New()返回的值上调用Interface()

func Execute3(i interface{}) {
    o := reflect.New(reflect.ValueOf(i).Elem().Type()).Interface()
    fmt.Sscanf("3", "%d", o)
    fmt.Println(*(o.(*int))) // 类型断言以提取指针以进行打印
}

这个Execute3()将按预期打印出3

Go Playground上尝试所有的例子。

英文:

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.

huangapple
  • 本文由 发表于 2016年2月5日 13:00:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/35216571.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定