我正在查看代码示例 sql.query 并且我对变量的初始化方式感到有些困惑。据我了解 var 关键字初始化变量,但如果您已经有这样的变量,最好“重用”它而不是重新初始化它。我知道我可能误解了 golang 规范,所以我希望这个问题能帮助我(也许其他人)做对。
rows, err := db.Query("SELECT name FROM users WHERE age=?", age)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name string
if err := rows.Scan(&name); err != nil {
log.Fatal(err)
}
fmt.Printf("%s is %d\n", name, age)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
为什么在循环内而不是在循环外初始化“名称”变量? (见下文)。在每个循环中重新初始化它的性能是不是降低了?
//how I would do this
rows, err := db.Query("SELECT name FROM users WHERE age=?", age)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
var name string //outside the loop
for rows.Next() {
if err := rows.Scan(&name); err != nil {
log.Fatal(err)
}
fmt.Printf("%s is %d\n", name, age)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
甚至更好地使用指针
rows, err := db.Query("SELECT name FROM users WHERE age=?", age)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
name := new(string) //pointer outside the loop
for rows.Next() {
if err := rows.Scan(name); err != nil {
log.Fatal(err)
}
fmt.Printf("%s is %d\n", name, age)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
最佳答案
除非您确定分配是性能瓶颈,否则我不会考虑这样过早的优化。毕竟,它甚至可能没有什么不同,所以最好在可读性/可维护性方面犯错。
一般来说,我建议对有意义的变量使用最小的范围。如果它们是堆栈分配的,那么它们将非常便宜——假设空间可用,它可能只涉及将变量初始化为零或其初始值。循环中范围内的堆栈分配变量也可能每次通过循环最终都具有相同的内存位置,因此将它们移出并没有什么好处。
话虽如此,何时在堆栈上分配变量并不总是很明显。如果编译器决定传递给 row.Scan
的指针可能会在函数调用之后保留(即转义),那么即使 name
已经用 var
定义,它也会在堆上分配。
类似地,如果转义分析确定变量没有转义,则使用 new
创建字符串变量的版本可能会决定将其放在堆栈中。
关于performance - 什么时候应该初始化一个新变量,什么时候不应该?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24540158/