Go语言同作用域短声明重定义报错,为何for循环内写法合法?
Go短声明
:=在循环中合法的原因 核心原理:Go的块级作用域规则
Go语言严格遵循块级作用域约束,变量的声明有效性仅在其所属的{}包裹的语法块内生效,短声明:=的重复定义校验也仅在同一个语法块内生效。
两个场景的差异对比
(A)报错的规则补充
你代码中两次a := make([]byte, 10)都处于main函数的同一个顶层语法块中,第二次执行:=时,左侧只有已经在当前块声明过的变量a,没有新增变量,不符合:=的语法要求,因此触发重复定义错误。
// 对应(A)的代码片段 a := make([]byte, 10) fmt.Println(a) a := make([]byte, 10) // 同一作用域无新变量,重复定义报错 fmt.Println(a)
(B)合法的原因
for循环的循环体{}本身是独立于外层main块的子作用域,且for循环的每一次迭代都会创建一个全新的、互不干扰的子作用域上下文:
- 单次迭代中,
r := make([]byte, 10)是在当前迭代的全新作用域内第一次声明变量r,完全符合:=的声明要求 - 上一次迭代声明的
r会随着上一次迭代的作用域销毁而失效,和当前迭代的r不属于同一个作用域,不存在重复定义的冲突
// 对应(B)的代码片段 for i := 0; i < 5; i++ { // 每次进入循环体都是全新的作用域,r是首次声明 r := make([]byte, 10) fmt.Println(r) } // 循环体外完全访问不到任何一次迭代声明的r,也验证了作用域的独立性
验证规则的反例
如果你把r声明在循环体外的同一作用域,再在循环体中用:=声明r就会触发和(A)一样的报错:
func main() { r := make([]byte, 10) // 外层作用域声明r for i := 0; i < 5; i++ { r := make([]byte, 10) // 同一子作用域内无新变量,触发重复定义错误 fmt.Println(r) } }
内容的提问来源于stack exchange,提问作者Ankur Agarwal
相关产品推荐
相关产品推荐

