":="中的全局变量赋值行为

huangapple go评论83阅读模式
英文:

Global variable assignment behavior in ":="

问题

尽管代码在main函数作用域中使用了:=,但全局变量level被赋予了来自getLevel()返回值的值。有人能用语言规范解释一下,这是如何可预测和有文档记录的行为吗?我的想法是更好地阅读规范,而我显然没有这样做。

代码:https://go.dev/play/p/4Pz0VL-2sNN

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
英文:

Even though code used := in main function scope, global level was assigned the value from the return value of getLevel(). Can someone explain with language spec, how this is a predictable and documented behavior. My idea is to better read the spec, which I'm clearly not doing.

Code: https://go.dev/play/p/4Pz0VL-2sNN

package main

import &quot;fmt&quot;

var level string

func main() {

	level, err := getLevel()
	fmt.Println(level, err)
	print(level)
}

func getLevel() (string, error) {
	return &quot;info&quot;, nil
}

func print(level string) {
	fmt.Printf(&quot;print: %s&quot;, level)
}

Output:-

info &lt;nil&gt;
print: info

答案1

得分: 3

在你的示例中,:= 实际上引入了一个名为 level 的新局部变量,根据规范(https://go.dev/ref/spec#Short_variable_declarations),全局作用域与任何函数作用域是不同的:

简短变量声明可以重新声明变量,前提是它们最初在同一代码块(或函数体的参数列表)中以相同的类型进行了声明。

你看到的行为之所以如此,是因为你对 level 的所有用法实际上都没有引用全局变量。main 中的用法是来自 := 的新局部变量,而 print 中的用法是函数参数。删除参数(包括声明和调用点),你将看到 printprint: 之后打印一个空字符串。

英文:

In your example, := does in fact introduce a new local variable called level, which is according to the specification since the global scope is distinct from any function scope:

> a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type

The reason you seeing the behavior that you describe is that none of your usages of level actually reference the global variable. The usage in main is the new local variable from :=, and the usage in print is the function parameter. Delete the parameter (both in the declaration and in the callsite), and you will see that print prints an empty string after print:.

huangapple
  • 本文由 发表于 2023年6月17日 07:09:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76494026.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定