2016-02-05 62 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