2015-07-20 41 views
2

我試圖從SQL服務器上的表中讀取所有行,並將它們存儲在字符串片中供以後使用。我遇到的問題是,以前掃描的行在每次掃描新行時都會被覆蓋,即使我已將所有可變字節切片轉換爲不可變字符串並將結果切片保存到另一切片。下面是我使用的代碼:SQL掃描的行被覆蓋

rawResult := make([]interface{}, len(cols)) // holds anything that could be in a row 
result := make([]string, len(cols)) // will hold all row elements as strings 
var results [][]string // will hold all the result string slices 
dest := make([]interface{}, len(cols)) // temporary, to pass into scan 
for i, _ := range rawResult { 
    dest[i] = &rawResult[i] // fill dest with pointers to rawResult to pass into scan 
} 
for rows.Next() { // for each row 
    err = rows.Scan(dest...) // scan the row 
    if err != nil { 
     log.Fatal("Failed to scan row", err) 
    } 
    for i, raw := range rawResult { // for each scanned byte slice in a row 
     switch rawtype := raw.(type){ // determine type, convert to string 
     case int64: 
      result[i] = strconv.FormatInt(raw.(int64), 10) 
     case float64: 
      result[i] = strconv.FormatFloat(raw.(float64), 'f', -1, 64) 
     case bool: 
      result[i] = strconv.FormatBool(raw.(bool)) 
     case []byte: 
      result[i] = string(raw.([]byte)) 
     case string: 
      result[i] = raw.(string) 
     case time.Time: 
      result[i] = raw.(time.Time).String() 
     case nil: 
      result[i] = "" 
     default: // shouldn't actually be reachable since all types have been covered 
      log.Fatal("Unexpected type %T", rawtype) 
     } 
    } 
    results = append(results, result) // append the result to our slice of results 
} 

我敢肯定,這事做與圍棋處理變量和內存的方式,但我似乎無法修復它。有人能解釋我不理解的東西嗎?

回答

1

您應該爲每個數據行創建新的片。請注意,slice有一個指向底層數組的指針,因此您添加到results中的每個slice在實際數據數組上都有相同的指針。這就是爲什麼你面對這種行爲。

+0

謝謝,這是非常不直觀的 –

+0

看看這篇文章。這是非常有用的http://blog.golang.org/slices – RoninDev

0

result := make([]string, len(cols))移動到您的for循環中,循環遍歷可用行。

1

當你使用func make()創建一個切片時,它返回一個類型(不是指向類型的指針)。但是,每次元素被重新分配時,它都不會分配新的內存。因此

結果:=化妝([]串,5)

將具有固定存儲器包含5個字符串。當一個元素被重新分配時,它將佔用與之前相同的內存,從而覆蓋舊的值。

希望下面的例子說清楚。

http://play.golang.org/p/3w2NtEHRuu

因此,在你的程序要更改同一存儲器的內容,並一次又一次地追加了。爲了解決這個問題,你應該在循環中創建你的結果片。

+1

'append'不只是複製內存的地址,請看看https://play.golang.org/p/7t4ie3JTOL它重複了值。 Slice是一個結構體,但事實是slice包含指向底層數組的指針。所以,雖然片已被複制,指針保持相同 – RoninDev

+1

是的。感謝澄清。 –