2016-02-05 60 views
1

我的扫描未更新其目标变量。我有点得到它的工作:扫描不起作用

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 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) 
      .... 
     } 
    } 
} 

两个日志消息是完全相同的Existing obj &{ 0 0 0 0 0 0 0 0 0 0 0 0}(空格是字符串字段)。这是因为大量使用反射来生成一个新的对象?在他们的文档中,它说我应该使用var ValueName type来定义我的目的地,但我似乎无法用反射来做到这一点。我意识到这可能是愚蠢的,但也许甚至只是指向我进一步调试的方向,这将是伟大的。我的Go技能非常缺乏!

回答

1

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

如果是这样,您必须将指针传递给Execute()。然后你只需要通过reflect.ValueOf(incrementedValue).Interface()Scan()。这是因为reflect.ValueOf(incrementedValue)是一个reflect.Value持有一个interface{}(你的参数的类型),它持有一个指针(你传递给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()) 
} 

它将打印1main(),如1设置内部Execute()的值。

如果你不想更新传递给Execute()变量,只是创建具有相同类型的新价值,因为你使用reflect.New()返回一个指针的Value,你必须通过existingObj.Interface()它返回一个interface{}拿着指针,你想要传递给Scan()的东西。 (你所做的是你通过一个指向reflect.ValueScan()这是不是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()另一个变体是如果你调用Interface()权由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 
} 

Execute3()将打印3预期。

尝试使用的所有示例Go Playground

+0

我接受任何类型“incrementedValue”的值,我只是试图创建一个未初始化的新变量,以提供给'bindQuery.Scan()'。我想要第二个,因为我经过并比较所有的领域。我没有测试过你发布的内容,但我想详细说明为什么我正在尝试做我自己的事情。实质上,最终目标是从数据库中获取对象,与递增的值进行比较,然后使用两者之间的更改更新数据库。相当简单,直到你想使它真正动态。 – electrometro

+0

@electrometro然后我的'Execute2()'和'Execute3()'对你来说可能是可行的。在我的答案结尾处还包含一个链接,用于在[Go Playground]上尝试我的代码(http://play.golang.org/p/DpuUcN3Af3)。 – icza

+0

第二个例子正是我所需要的。这是一个漫长的夜晚,只要我今天早上看到它很有意义。谢谢! – electrometro