3 回答
TA贡献1830条经验 获得超3个赞
因为可以有多个具有相同名称的变量,只要它们具有不同的作用域即可。内部作用域中的变量将遮蔽外部作用域中的变量。
因此,如果我们分解您的示例
func badQueue() {
// queue from outer scope, lets call it A
queue := []int{0,1,2,3,4,5}
// the only visible queue here is A, so len(queue) will always refer to A
for len(queue) > 0 {
// same thing here, the only visible queue is A, so queue[0] and queue[1:]
// both refer to A
// We are also declaring new variables, queue and current
// This queue is now shadowing the outer queue, let's call this one B
current, queue := queue[0], queue[1:]
// Here queue will refer to B
fmt.Println(current, queue)
// When the current iteration of the loop ends current and queue B is destroyed
// because they go out of scope and the loop start over with A unchanged
}
}
TA贡献1818条经验 获得超7个赞
要了解它在 Go 中的工作原理,需要两点:
范围
Go 使用块作用域,每个大括号对将创建一个新作用域,如果内部作用域中的标识符具有相同的声明名称,则它们将隐藏外部作用域中的标识符。
func main() {
var name string = "Golang"
fmt.Printf("Outer Scope: %s\n", name) // Print "Golang"
{
var name string = "Java"
fmt.Printf("Inner Scope: %s\n", name) // Print "Java"
}
fmt.Printf("Outer Scope: %s\n", name) // Print "Golang" again
}
短变量声明
Operator是一个复合操作,它将在一个语句中做几件事:声明,类型推断和赋值,基本上你可以把它当作一个语法糖。以下 S1 和 S2 的代码示例是等效的::=
func main() {
// S1
var name string = "Golang"
// S2
name := "Golang"
}
考虑到以上两点,您的代码在翻译后将如下所示:
func badQueue() {
queue := []int{0,1,2,3,4,5}
for len(queue) > 0 {
var current int
var queue []int
current, queue = queue[0], queue[1:]
fmt.Println(current, queue)
}
}
很明显,外部不受影响内部循环。queuefor
顺便说一句,对于左侧的每个变量,编译器将查找当前块范围以尝试解析标识符,如果之前已经声明过,编译器将重用它而不是创建一个新的。但是,如果之前声明了所有 lhs 变量,编译器将报告一个错误,并显示消息“:=的左侧没有新变量”。请查看以下代码::=
func main() {
var name string
name, age := "Golang", 10 // reuse the above 'name' and create a new variable 'age'
var tom, jerry string
tom, jerry := "Tom", "Jerry" // no new variables on left side of :=
}
新的编译器实现在这里,适合那些对细节感兴趣的人。
- 3 回答
- 0 关注
- 97 浏览
添加回答
举报