当前位置: 首页 > 面试题库 >

如何在不替换Golang中前一行的情况下将最后一个sql行添加到列表中

薛浩言
2023-03-14
问题内容

这段html" target="_blank">代码提供了AFAIK正确的JSON输出[{},{}],但是每行都被附加并替换了之前的所有行,因此结果仅显示最后一行的副本。

var rows *sql.Rows
rows, err = db.Query(query)
cols, _ := rows.Columns()
colnames, _ := rows.Columns()
vals := make([]interface{}, len(cols))

for i, _ := range cols {
   vals[i] = &cols[i]
}

m := make(map[string]interface{})

for i, val := range vals {
  m[colnames[i]] = val
}

list := make([]map[string]interface{}, 0)
for rows.Next() {
err = rows.Scan(vals...)
   list = append(list, m)
}
json, _ := json.Marshal(list)
fmt.Fprintf(w,"%s\n", json)

这是幕后循环遍历行的情况:

循环1:{“ ID”:“ 1”,“ NAME”:“ John”

循环2:{“ ID”:“ 2”,“ NAME”:“ Jane Doe”} {“ ID”:“ 2”,“ NAME”:“ Jane Doe”}

循环3:{“ ID”:“ 3”,“ NAME”:“ Donald Duck”} {“ ID”:“ 3”,“ NAME”:“ Donald Duck”}

rows.Scan会获取正确的值,但会附加并替换所有先前的值。

最终的输出是这个

[{“ ID”:“ 3”,“ NAME”:“ Donald Duck”},{“ ID”:“ 3”,“ NAME”:“ Donald Duck”},{“
ID”:“ 3”,“ NAME ”:“唐老鸭”}]

但是应该是这样的:

[{{ID}:“ 1”,“ NAME”:“ John Doe”},{“ ID”:“ 2”,“ NAME”:“ Jane Doe”},{“ ID”:“
3”,“ NAME” ”:“唐老鸭”}]

我究竟做错了什么?

您可能对此表示反对,但请解释原因。我仍然是Golang的新手,想学习。


问题答案:

我修复了它并用注释解释了您做错了什么:

// 1. Query
var rows *sql.Rows
rows, err = db.Query(query)
cols, _ := rows.Columns()

// 2. Iterate
list := make([]map[string]interface{}, 0)
for rows.Next() {
    vals := make([]interface{}, len(cols))
    for i, _ := range cols {
        // Previously you assigned vals[i] a pointer to a column name cols[i].
        // This meant that everytime you did rows.Scan(vals),
        // rows.Scan would see pointers to cols and modify them
        // Since cols are the same for all rows, they shouldn't be modified.

        // Here we assign a pointer to an empty string to vals[i],
        // so rows.Scan can fill it.
        var s string
        vals[i] = &s

        // This is effectively like saying:
        // var string1, string2 string
        // rows.Scan(&string1, &string2)
        // Except the above only scans two string columns
        // and we allow as many string columns as the query returned us — len(cols).
    }

    err = rows.Scan(vals...)

    // Don't forget to check errors.
    if err != nil {
        log.Fatal(err)
    }

    // Make a new map before appending it.
    // Remember maps aren't copied by value, so if we declared
    // the map m outside of the rows.Next() loop, we would be appending
    // and modifying the same map for each row, so all rows in list would look the same.
    m := make(map[string]interface{})
    for i, val := range vals {
        m[cols[i]] = val
    }
    list = append(list, m)
}

// 3. Print.
b, _ := json.MarshalIndent(list, "", "\t")
fmt.Printf("%s\n", b)

不用担心,当我还是初学者时,这也很难理解。

现在,有趣的是:

var list []map[string]interface{}
rows, err := db.Queryx(query)
for rows.Next() {
    row := make(map[string]interface{})
    err = rows.MapScan(row)
    if err != nil {
      log.Fatal(err)
    }
    list = append(list, row)
}

b, _ := json.MarshalIndent(list, "", "\t")
fmt.Printf("%s\n", b)

这样做与上面的代码相同,但使用sqlx。简单一点,不是吗?

sqlx是在database/sql方法之上的扩展,可以直接将行扫描到映射和结构,因此您不必手动进行。

我认为您的模型作为结构看起来更好:

type Person struct {
    ID int
    Name string
}

var people []Person
rows, err := db.Queryx(query)
for rows.Next() {
    var p Person
    err = rows.StructScan(&p)
    if err != nil {
        log.Fatal(err)
    }
    people = append(people, p)
}

你不觉得吗



 类似资料:
  • 但是当我重新加载/刷新数据库时,没有新的数据被追加到数据库中...这里是我的代码.... 当我运行它时,它显示没有错误,但数据从来没有进入数据库,我是哪里出错了?.....

  • 问题内容: 我有一个包含800,000个没有主键的条目的表。我不允许添加主键,我无法按 TOP 1 .... ORDER BY DESC进行 排序, 因为完成此任务需要几个小时 。因此,我尝试了以下方法: 当然,这是行不通的。 无论如何要使用此代码或更好的代码来检索表中的最后一行? 问题答案: 我假设当您说“最后一行”时,您的意思是“最后创建的行”。 即使您具有主键,使用它来确定行的创建顺序仍然不

  • rbindlist做的正是我需要的,但'do.call'做不到! do.Call不是我想要的

  • 我试图让发送消息给另一方的用户和接收消息的用户在每行的一行中。 那么oracle sql查询应该是什么呢

  • 我有一个对象, 现在我想在中添加一个换行符。我该怎么做? 不工作。所以,我在考虑使用Unicode编写一个新行。这会有帮助吗?如果有,怎么加一个?

  • 我有一个作为模板的电子表格,最后两行以某种特定的方式格式化(颜色和字体)。 它看起来像这样: 我想做的是插入尽可能多的“占位符”行,让最后一行“滑”下来。 到目前为止,我尝试了,它确实插入了新行,但不会向下移动最后一行的颜色。这样我就可以在电子表格中找到我想要的数据,但是颜色格式错误(基本上第三行总是有彩色背景,而最后一行没有)。 我想做的伪代码是: 计算我需要添加多少占位符行, 获取电子表格 剪