英文:
Cannot reuse a single variable in for loop
问题
我想在每次迭代中创建一个指针并在其中使用它,但最后得到的所有值都相同。所以我找到了一种解决方案,即在每次迭代中创建指针。
但是这种方法似乎浪费了很多内存。
在Go语言中有没有一种重用同一变量的方法?
以下是我的代码:
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()
for rows.Next() {
a := new(Scheduler)
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
的变量上,尽管我在每次迭代中将新的内容扫描到它中,但它只显示最后一个,并且结果切片只包含多个相同的最后一个项。
英文:
I want to create a pointer and use it in every iteration but in the and I get all the same values. So I found the solution using creating the pointer in every iteration.
But this approach seems wasting a lot of memory.
Is there a way to reuse the same variable in Go?
Here is my code
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
}
hereThe problem is with the variable called a
although I am scanning new stuff into it in every iteration it just keeps showing the last one and the results slice contains just the last item multiple times
答案1
得分: 4
在你的应用程序中,除非有证据表明垃圾回收(GC)是一个瓶颈,否则不必担心它。当从数据库读取数据时,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
所以最终两种方式产生的分配数量完全相同。
从数据库读取到结构体的典型代码如下:
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 { // 不要忘记检查 rows.Err()
return nil, err
}
return results, nil
英文:
Don't worry about GC until you have proof that it is a bottleneck in your application. When reading data from DB, GC will never be a bottleneck for you. This is a simple benchmark:
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)
}
}
}
Results of running 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
So in the end both ways result in exactly the same amount of allocations.
And the typical reading from DB into struct looks like this:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论