如何避免对同一内存块的切片引用

时间:2015-10-30 12:17:41

标签: sql go

我从数据库查询并尝试插入切片时遇到问题(包含一些map [string] interface {}) 即使我已经使用make来创建一个新的内存块,切片似乎总是映射到同一个内存块。

type DBResult []map[string]interface{}

func ResultRows(rows *sql.Rows, limit int) (DBResult, error) {
    cols, err := rows.Columns()
    if err != nil {
        return nil, err
    }

    vals := make([]sql.RawBytes, len(cols))
    scanArgs := make([]interface{}, len(vals))
    for i := range vals {
        scanArgs[i] = &vals[i]
    }

    if limit > QUERY_HARD_LIMIT {
        limit = QUERY_HARD_LIMIT
    }

    res := make(DBResult, 0, limit)
    for rows.Next() {
        err = rows.Scan(scanArgs...)
        m := make(map[string]interface{})

        for i := range vals {
            m[cols[i]] = vals[i]
        }
        /* Append m to res */
        res = append(res, m)
        /* The value of m has been changed */
        fmt.Printf("lib: m:\n\n%s\n\n", m)
        /* When printing res, always mapping to the same memory block */
        fmt.Printf("lib: res:\n\n%s\n\n", res)
    }

    return res, err
}

以下是结果,你可以发现res的内容是相同的

  

m = map [评论:first_comment id:0]

     

res = [map [id:0 comment:first_comment]]

     

m = map [id:1 comment:first_comment]

     

res = [map [id:1 comment:first_comment] map [id:1 comment:first_comment]]

     

m = map [id:2 comment:first_comment]

     

res = [map [id:2 comment:first_comment] map [id:2 comment:first_comment] map [id:2 comment:first_comment]]

我期待res = [map [id:0 comment:first_comment] map [id:1 comment:first_comment] map [id:2 comment:first_comment]]

感谢您收看

1 个答案:

答案 0 :(得分:-1)

根据行(https://golang.org/pkg/database/sql/#Rows.Scan)的文件:

扫描将当前行中的列复制到dest指向的值。

如果参数的类型为* [] byte,则Scan会在该参数中保存相应数据的副本。该副本由调用者拥有,可以无限期地修改和保留。可以通过使用* RawBytes类型的参数来避免副本;有关其使用的限制,请参阅RawBytes的文档。

如果参数的类型为* interface {},则Scan会复制底层驱动程序提供的值而不进行转换。如果值为[] byte类型,则复制并且调用者拥有结果。

在您的情况下,您使用RawBytes作为Scan的参数。这可能是你遇到的问题。尝试其他类型作为扫描功能的参数。