3 回答
![?](http://img1.sycdn.imooc.com/54584d1300016b9b02200220-100-100.jpg)
TA贡献1900条经验 获得超5个赞
您所遇到的通常称为“可变阴影”。当您:=在内部范围内使用任何变量时,包括在语句中if,for尽管没有大括号,但新值和类型与该变量相关联:
n := "Example"
//Prints the string variable `n` to standard output and
// returns the number of bytes written in int variable `n` and
// an error indicator in error variable `err`.
if n, err := fmt.Println(n); err != nil {
panic(err)
} else {
fmt.Println(n, "bytes written")
}
//Prints the string variable `n` to standard output.
fmt.Printf("n = %q\n", n)
输出:
Example
8 bytes written
n = "Example"
有几种不同的方法可以解决此问题:
在使用它们之前声明您需要的变量并使用普通赋值
=
使用不同的变量名
创建一个新范围并保存变量的值以供以后访问,根据需要使用变量名称
:=
,并在范围结束之前恢复该值;使用不同的变量名通常更容易,因为无论如何您都在创建另一个变量
也可能发生相反的效果,您在内部范围内声明某些内容但没有意识到:
if _, err := fmt.Println(n); err != nil {
panic(err)
} else {
fmt.Println(n, "bytes written")
}
//undefined: err
if _, err = fmt.Println(n); err != nil {
//undefined: err
panic(err)
}
在使用它们之前声明您需要的变量并使用普通赋值
=
将第一个
:=
和if
语句分开,因此变量按预期声明;这允许您=
在该范围的上下文以及包含它的任何范围内使用该变量的所有其他实例更改
=
to 的所有实例:=
以修复错误
请注意,当函数返回多个值时,您可能会在最后两种情况下遇到变量阴影问题,但这可以按照上面的说明解决。
在 Go Playground 上尝试这两个示例。
您的最后一个示例说明了声明和初始化新变量b同时还为现有变量赋值的组合a。没有创建新范围,因此您不会隐藏原始变量a,您可以通过a在每次分配之后(但在下一个声明/分配之前)打印地址来验证:
a := 1
fmt.Println(&a)
a, b := 2, 3
fmt.Println(&a)
a = b // avoids a "declared but not used" error for `b`
当然,如果你没有声明b,那么你会从编译器收到一个错误,即:=第二个声明的左侧没有新变量,这是一种迂回的说法,你正在尝试声明a在同一范围内两次。
请注意,如果仔细应用此想法,也可用于查找被遮蔽的变量。例如,您的示例中的“不工作”代码将打印不同的地址a,具体取决于a内部范围内部是否已声明:
a := 1
{
fmt.Println(&a) // original `a`
a, b := 2, 3
fmt.Println(&a) // new `a`
a = b // avoids a "declared but not used" error for `b`
}
fmt.Println(&a) // original `a`
![?](http://img1.sycdn.imooc.com/545866130001bfcb02200220-100-100.jpg)
TA贡献1847条经验 获得超11个赞
根据 golang 的文档:
在块中声明的标识符可以在内部块中重新声明。
这正是您的示例所显示的内容,由于“:=”,因此在括号内重新声明了 a,并且从未使用过。
一个解决方案是声明两个变量然后使用它:
var a, b int
{
b, a = 2, 3
fmt.Println(b)
}
fmt.Println(a)
![?](http://img1.sycdn.imooc.com/545865470001bf9402200220-100-100.jpg)
TA贡献2016条经验 获得超9个赞
您的问题有两部分:
第一部分:
= 只是分配
:= 是为功能块(非全局)内的新变量(至少一个新变量)定义和分配,工作示例:
package main
import (
"fmt"
)
func main() {
var u1 uint32 //declare a variable and init with 0
u1 = 32 //assign its value
var u2 uint32 = 32 //declare a variable and assign its value at once
//declare a new variable with defining data type:
u3 := uint32(32) //inside the function block this is equal to: var u3 uint32 = 32
fmt.Println(u1, u2, u3) //32 32 32
//u3 := 20//err: no new variables on left side of :=
u3 = 20
fmt.Println(u1, u2, u3) //32 32 20
u3, str4 := 100, "str" // at least one new var
fmt.Println(u1, u2, u3, str4) //32 32 100 str
}
第二部分:
在块中声明的标识符可以在内部块中重新声明。
这里有 4 个不同的可变范围和阴影工作示例:
限制变量范围的简单方法:
package main
import "fmt"
func main() {
i := 1
j := 2
//new scope :
{
i := "hi" //new local var
j++
fmt.Println(i, j) //hi 3
}
fmt.Println(i, j) //1 3
}
使用函数调用限制变量范围:
package main
import "fmt"
func fun(i int, j *int) {
i++ //+nice: use as local var without side effect
*j++ //+nice: intentionally use as global var
fmt.Println(i, *j) //11 21
}
func main() {
i := 10 //scope: main
j := 20
fun(i, &j)
fmt.Println(i, j) //10 21
}
在语句中使用简写赋值:
package main
import "fmt"
func main() {
i := 10 //scope: main
j := 4
for i := 'a'; i < 'b'; i++ {
fmt.Println(i, j) //97 4
}
fmt.Println(i, j) //10 4
if i := "test"; len(i) == j {
fmt.Println(i, j) // i= test , j= 4
} else {
fmt.Println(i, j) //test 40
}
fmt.Println(i, j) //10 4
}
阴影全局变量:
package main
import "fmt"
var i int = 1 //global
func main() {
j := 2
fmt.Println(i, j) //1 2
i := 10 //Shadowing global var
fmt.Println(i, j) //10 2
fun(i, j) //10 2
}
func fun(i, j int) {
//i := 100 //no new variables on left side of :=
fmt.Println(i, j) //10 2
}
- 3 回答
- 0 关注
- 163 浏览
添加回答
举报