我有以下代码:
if err == nil {
body, err := ioutil.ReadAll(response.Body)
if err == nil {
dataMap := &models.UserResponse{}
json.Unmarshal(body, &dataMap)
if dataMap.User == (models.UserId{}) {
err = fmt.Errorf("unauthorized")
fmt.Println(err) // when unathorized, prints unauthorized
}
}
}
fmt.Println(err) // always prints nil
Run Code Online (Sandbox Code Playgroud)
该Println内部if dataMap.User ...打印"unauthorized",而最后Println总是打印nil.
我不知道它为什么会发生,在这个函数的开头err声明var err error.
原因在Spec:Short变量声明中详细说明:
与常规变量声明不同,短变量声明可以重新声明变量,前提是它们最初在同一个块中声明(或者如果块是函数体的参数列表)具有相同的类型,并且至少有一个非空变量是新的.因此,重新声明只能出现在多变量简短声明中.重新声明不会引入新变量; 它只是为原始分配一个新值.
当使用带有多个变量的短变量声明时,如果已在同一个块中声明了赋值,则只会对现有变量进行赋值.由于你的case err变量存在于if块之前,因此将在块内创建一个新err变量,该变量if与"outsider" err变量无关(除了共享其名称).在短变量声明之后,外部err将在块中被遮蔽if.
所以会发生什么,在if你内部,你创建一个新的err变量,并为其分配一个值,然后打印出来.
在if语句之后,您将打印err在if块内未更改其值的外部变量,因此它仍然存在nil.
看这个例子:
var err error
fmt.Println("outside:", err) // nil
{
// A new err variable, shadows the outer:
i, err := strconv.Atoi("a")
fmt.Println("inside:", i, err) // 0 strconv.Aoti: parsing "a": invalid syntax
}
fmt.Println("outside:", err) // nil, because this was never changed
// Now this will change the "outer" err:
j, err := strconv.Atoi("a")
fmt.Println("outside:", j, err) // 0 strconv.Aoti: parsing "a": invalid syntax
Run Code Online (Sandbox Code Playgroud)
输出(在Go Playground上试试):
outside: <nil>
inside: 0 strconv.Atoi: parsing "a": invalid syntax
outside: <nil>
outside: 0 strconv.Atoi: parsing "a": invalid syntax
Run Code Online (Sandbox Code Playgroud)
如果要在创建新变量时使用(赋值)"外部"变量,则不能在"嵌套"块中使用短变量声明,而只能使用简单赋值,在这种情况下,您还必须声明其他变量是先验的,如下例所示:
if err == nil {
var body []byte
body, err = ioutil.ReadAll(response.Body)
// ... rest...
}
Run Code Online (Sandbox Code Playgroud)
查看相关问题:
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |