将数据库行读入映射并追加到映射切片中。

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

Reading database rows into map and appending to a slice of maps

问题

我正在尝试使用映射和映射的切片来存储从数据库查询返回的行。但是,在每次迭代的rows.Next()和最后一次迭代中,我得到的都是相同查询结果的切片。似乎问题与我存储cols的内存位置有关,但是我目前还没有解决它。

你在这里漏掉了什么:

以下是源代码:

package main

import (
	"database/sql"
	_ "github.com/lib/pq"

	"fmt"
	"log"

	"reflect"
)
var myMap = make(map[string]interface{})
var mySlice = make([]map[string]interface{}, 0)

func main(){
	fmt.Println("this is my go playground.")

	// DB Connection-
    db, err := sql.Open("postgres", "user=postgres dbname=proj2-dbcruddb-dev password=12345 sslmode=disable")
    if err != nil {
        log.Fatalln(err)
    }
	rows, err := db.Query("SELECT id, username, password FROM userstable")
	defer rows.Close()
	if err != nil {
	    log.Fatal(err)
	}

	colNames, err := rows.Columns()
	if err != nil {
	    log.Fatal(err)
	}
	cols := make([]interface{}, len(colNames))
	colPtrs := make([]interface{}, len(colNames))
	for i := 0; i < len(colNames); i++ {
	    colPtrs[i] = &cols[i]
	}

	for rows.Next() {
	    err = rows.Scan(colPtrs...)
	    if err != nil {
	        log.Fatal(err)
	    }
		fmt.Println("cols: ", cols)

	    for i, col := range cols {
	        myMap[colNames[i]] = col
	    }
		mySlice = append(mySlice, myMap)
		
	    // Do something with the map
	    for key, val := range myMap {
	        fmt.Println("Key:", key, "Value:", val, "Value Type:", reflect.TypeOf(val))
	    }
		fmt.Println("myMap: ", myMap)
		fmt.Println("mySlice: ", mySlice)
		
	}
	fmt.Println(mySlice)
}

希望对你有所帮助!

英文:

I am trying to use maps and slice of those maps to store rows returned from a database query. But what I get in every iteration of the rows.Next() and in final is the slice of the one same row from the query. It seems the problem is related to the memory place being same I store the cols, yet I could not resolve it until now.

What is the thing am I missing here:

The source code is as follows:

package main
import (
&quot;database/sql&quot;
_ &quot;github.com/lib/pq&quot;
&quot;fmt&quot;
&quot;log&quot;
&quot;reflect&quot;
)
var myMap = make(map[string]interface{})
var mySlice = make([]map[string]interface{}, 0)
func main(){
fmt.Println(&quot;this is my go playground.&quot;)
// DB Connection-
db, err := sql.Open(&quot;postgres&quot;, &quot;user=postgres dbname=proj2-dbcruddb-dev password=12345 sslmode=disable&quot;)
if err != nil {
log.Fatalln(err)
}
rows, err := db.Query(&quot;SELECT id, username, password FROM userstable&quot;)
defer rows.Close()
if err != nil {
log.Fatal(err)
}
colNames, err := rows.Columns()
if err != nil {
log.Fatal(err)
}
cols := make([]interface{}, len(colNames))
colPtrs := make([]interface{}, len(colNames))
for i := 0; i &lt; len(colNames); i++ {
colPtrs[i] = &amp;cols[i]
}
for rows.Next() {
err = rows.Scan(colPtrs...)
if err != nil {
log.Fatal(err)
}
fmt.Println(&quot;cols: &quot;, cols)
for i, col := range cols {
myMap[colNames[i]] = col
}
mySlice = append(mySlice, myMap)
// Do something with the map
for key, val := range myMap {
fmt.Println(&quot;Key:&quot;, key, &quot;Value:&quot;, val, &quot;Value Type:&quot;, reflect.TypeOf(val))
}
fmt.Println(&quot;myMap: &quot;, myMap)
fmt.Println(&quot;mySlice: &quot;, mySlice)
}
fmt.Println(mySlice)
}

答案1

得分: 1

这是因为你在切片中存储的是一个指向映射的指针,而不是映射的副本。

根据Go maps in action:

> 映射类型是引用类型,就像指针或切片一样...

由于你在更新映射之前在循环外创建了映射,你不断用新数据覆盖映射中的数据,并且每次将指向同一个映射的指针追加到切片中。因此,在切片中你得到了相同内容的多个副本(即从表中读取的最后一条记录)。

为了解决这个问题,将var myMap = make(map[string]interface{})移到for rows.Next()循环内部,这样每次迭代都会创建一个新的映射,并将其追加到切片中。

英文:

This is because what you are storing in the slice is a pointer to a map rather than a copy of the map.

From Go maps in action:

> Map types are reference types, like pointers or slices...

Since you create the map outside the loop that updates it, you keep overwriting the data in the map with new data and are appending a pointer to the same map to the slice each time. Thus you get multiple copies of the same thing in your slice (being the last record read from your table).

To handle, move var myMap = make(map[string]interface{}) into the for rows.Next() loop so a new map is create on each iteration and then appended to the slice.

huangapple
  • 本文由 发表于 2015年6月1日 16:36:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/30569005.html
匿名

发表评论

匿名网友

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

确定