Go语言中main函数用:=为何能赋值全局变量?求规范解释
为什么Go语言中短变量声明
:=会修改全局变量? 你遇到的这个情况是Go语言短变量声明(:=)的标准行为,完全符合语言规范,下面结合你的代码详细解释:
你的代码示例
package main import "fmt" var level string // 包级全局变量 func main() { level, err := getLevel() // 这里用了短变量声明 fmt.Println(level, err) print(level) } func getLevel() (string, error) { return "info", nil } func print(level string) { fmt.Printf("print: %s", level) }
输出结果
info <nil> print: info
规范层面的解释
根据Go语言规范中短变量声明的规则:
- 短变量声明语句
a, b := x, y的核心作用是「声明新变量并赋值」,但存在例外情况:如果左边的某个变量已经在包含当前代码块的外层作用域中被声明,并且该变量的类型与赋值的表达式类型兼容,那么语句不会重新声明这个变量,而是直接对其进行赋值。
放到你的代码里看:
- 包级作用域已经声明了
string类型的level变量; - 在main函数的代码块中,
level, err := getLevel()这句里:err是当前块中未声明的新变量,所以会被声明为error类型并赋值;level是外层(包级)已存在的变量,类型string和getLevel()返回的string完全匹配,因此这里不会在main函数中创建新的局部level变量,而是直接给包级的level变量赋值为"info";
- 后续调用
print(level)时,传入的是包级的level变量值,所以print函数输出"info"。
补充验证
如果把包级level的类型改成int,再运行代码:
var level int // 类型改为int
此时main里的level, err := getLevel()会在main函数中声明一个新的局部string类型level变量(因为外层的int类型和赋值的string类型不兼容),这时候全局的level不会被修改,仍然是默认值0。
内容的提问来源于stack exchange,提问作者shadyabhi
相关产品推荐
相关产品推荐

