Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 什么时候应该初始化新变量,什么时候不应该?_Performance_Go - Fatal编程技术网

Performance 什么时候应该初始化新变量,什么时候不应该?

Performance 什么时候应该初始化新变量,什么时候不应该?,performance,go,Performance,Go,我正在看代码示例,对变量的初始化方式有点困惑。据我所知,var关键字初始化变量,但如果您已经有了这样一个变量,最好是“重用”它,而不是重新初始化它。我知道我可能误解了golang规范,所以我希望这个问题能帮助我(也许还有其他人)正确理解 rows, err := db.Query("SELECT name FROM users WHERE age=?", age) if err != nil { log.Fatal(err) } defer r

我正在看代码示例,对变量的初始化方式有点困惑。据我所知,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)
    }
为什么“name”变量在循环内而不是在循环外初始化?(见下文)。在每个循环上重新初始化不是性能较差吗

//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)
        }

除非你已经确定分配是一个性能瓶颈,否则我不会考虑这种过早的优化。毕竟,它甚至可能没有什么不同,所以最好在可读性/可维护性方面出错

一般来说,我建议对变量使用有意义的最小范围。如果它们是堆栈分配的,那么它们将非常便宜——假设空间可用,它可能只涉及将变量初始化为零或其初始值。循环中的堆栈分配变量的作用域可能每次通过循环都会以相同的内存位置结束,因此将它们移出不会有太多好处

尽管如此,在堆栈上分配变量的时间并不总是显而易见的。如果编译器决定传递给
行.Scan
的指针可能会保留在函数调用之后(即,它会转义),那么
名称
将被分配到堆上,即使它是用
var
定义的


类似地,如果转义分析确定变量没有转义,则使用
new
创建字符串变量的版本可能会决定将其放在堆栈上。

name
在循环之前声明,否则它将被限定在if块的范围内,而不在该块之外的范围内(阅读:以后不能使用它)。循环不会重新初始化它,它只是重新使用它。块(循环)在变量声明之后。只想指出,
name
实际上是在循环中声明的,而不是之前(在sql文档中)。在我看来,我似乎错过了块范围的事情。我不知道
块是否具有这种隔离property@hey:它包含在:。中。这有点烦人。例如,我有一些准备好的语句,因此如果它们没有正确使用,性能肯定会提高(即缓存)。但是,如果在每个循环上初始化了一个新的连接/语句,这会使它们变得无用。我想在循环中声明它们,但有时会得到“太多连接”错误,因此我只能假设Go在每个循环上初始化它们,从而消除了对Go SQL示例的混淆。如果您希望在循环的迭代之间使用相同的值,则在循环外部声明变量是有意义的。不过,在您的问题中,您只在循环内使用了一个变量。