无法在Golang中重用for循环中的单个变量

时间:2017-06-23 12:13:19

标签: pointers go closures

我想创建一个指针,并在每次迭代中使用它,但在和我得到所有相同的值。所以我发现解决方案使用在每次迭代中创建指针。 但这种方法似乎浪费了很多记忆。

有没有办法在golang中重用相同的变量?

这是我的代码

func GetSchedules(start, end time.Time, usr *user.User) ([]*Scheduler, error) {
    queryStr := []string{"SELECT account_id,link,text,time,image_links from", Table, "where user_id=?"}
    var results = make([]*Scheduler, 0)
    rows, err := DB.MYSQL_DB.Query(strings.Join(queryStr, " "), usr.Id.Hex())
    if nil != err {
        return results, err
    }
    defer rows.Close()
    a := new(Scheduler)
    for rows.Next() {

        cols := []interface{}{&a.AccountId, &a.Link, &a.Text, &a.Time, &a.Images}
        fmt.Println(rows.Scan(cols...))
        results = append(results, a)

    }

    return results, nil
}

这里的问题是名为a的变量,虽然我在每次迭代中都会扫描新内容但它只是显示最后一个而结果切片只包含多次最后一项

1 个答案:

答案 0 :(得分:4)

在您证明它是您的应用程序的瓶颈之前,请不要担心GC。从DB读取数据时,GC永远不会成为您的瓶颈。这是一个简单的基准:

func BenchmarkReallocate(b *testing.B) {
    for i := 0; i < b.N; i++ {
        results := make([]*foo, 0)
        for i := 0; i < 100; i++ {
            f := new(foo)
            f.bar = "baz"
            results = append(results, f)
        }
    }
}

func BenchmarkReuse(b *testing.B) {
    for i := 0; i < b.N; i++ {
        results := make([]*foo, 0)
        var f *foo
        for i := 0; i < 100; i++ {
            f = new(foo)
            f.bar = "baz"
            results = append(results, f)
        }
    }
}

运行go test -bench . -benchmem

的结果
BenchmarkReallocate-8         300000          4416 ns/op        3640 B/op        108 allocs/op
BenchmarkReuse-8              300000          4359 ns/op        3640 B/op        108 allocs/op
PASS

因此,最终两种方式都会产生完全相同的分配量。

从DB到struct的典型读数如下:

rows, err := db.Query("SELECT * FROM foo")
if nil != err {
    return nil, err
}
defer rows.Close()
results := make([]*Scheduler, 0)
for rows.Next() {
    var s Scheduler
    if err := rows.Scan(&s.Id, &s.Name, &s.Something); err != nil {
        return nil, err
    }
    results = append(results, &s)
}
if err := rows.Err(); err != nil { // Don't forget to check rows.Err()
    return nil, err
}
return results, nil