Golang函数包含匿名作用域

7

请问什么情况下和为什么我会在函数内使用匿名作用域?(我不确定它的实际名称)。

我被分配维护一些遗留代码,其中一些函数包含了我之前从未见过的“作用域”:

(为演示目的而简化)

func DoSomething(someBoolValue bool) string {
    if someBoolValue {
        // do some stuff
        return "yes"
    }
    {
        // weird scope code
    }
    return "no"
}

我创建了一个Go Playground,用于展示一些实际代码(会出现错误)。

1
如果您需要为两个不同的变量使用相同的标识符,即您可能会在块中重新定义someBoolValue:=“banana”,并且它仍将是块后传入的值。(如其他答案所述,在for/if/switch/select/func块内也会发生相同的作用域) - Plato
2个回答

5
它被称为变量作用域和遮蔽:
Go使用块进行词法作用域: 1.预声明标识符的作用域是宇宙块。 2.在顶层(任何函数外部)声明的常量、类型、变量或函数(但不包括方法)标识符的作用域是包块。 3.导入包的包名称的作用域是包含导入声明的文件块。 4.方法接收器、函数参数或结果变量标识符的作用域是函数体。 5.在函数内声明的常量或变量标识符的作用域从ConstSpec或VarSpec(短变量声明的ShortVarDecl)的结尾开始,并在最内层包含块的结尾结束。 6.在函数内声明的类型标识符的作用域从TypeSpec中的标识符开始,并在最内层包含块的结尾结束。在块中声明的标识符可以在内部块中重新声明。当内部声明的标识符处于作用域时,它表示内部声明声明的实体。
包子句不是声明;包名称不出现在任何作用域中。其目的是标识属于同一包的文件并指定导入声明的默认包名称。
您的工作示例代码:
package main

import (
    "fmt"
)

func main() {
    i := 10
    {
        i := 1
        fmt.Println(i)  // 1
    }
    fmt.Println(i)  // 10
}

输出:

1
10

请查看:Go语言中的变量作用域和变量遮蔽在哪里使用?


3
在Go中,{}形成一个语法块。每个块都定义了一个新的作用域。例如,您可以使用iffor来使用这些相同的块。
就您的代码而言,我猜它们主要是为了可读性。您可以重用或隐藏在封闭作用域中定义的变量,以利用可能更清晰地声明代码意图的变量名称。
除此之外,它们还可以用于将一组相关语句分组,以提高可读性。
要了解它们的行为,请参考@Amd的答案。

1
谢谢回复。我认为它们在我的例子中可能被不必要地使用了,但现在我理解了它们的正确用法。 - syscll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接