golang if初始化语句的作用域为内部if块。为什么?

时间:2018-08-28 09:44:27

标签: if-statement go scope

我在代码中发现了一个错误

func receive() (err error) {
    if v, err := produce(); err == nil {
        fmt.Println("value: ", v)
    }
    return
}

此函数永远不会返回错误,但是我绝对确定会出现。

经过一些测试,我了解到err在if语句中被重新声明。不仅如此-所有变量始终在if语句内的短变量赋值中重新声明,尽管它们之前已声明过。

这是工作代码

func receive() (err error) {
    v, err := produce()
    if err == nil {
        fmt.Println("value: ", v)
    }
    return
}

这里是一个示例:https://play.golang.org/p/1AWBsPbLiI1

好像if语句

//some code
if <init_statement>; <expression> {}
//more code

等效于

//some code
{
    <init_statement>
    if expression {}
}
//more code

所以,我的问题:

1)为什么不使用现有变量

2)为什么文档/语言规范中未提及这种范围定义

3)为什么编译器没有说没有人返回值

2 个答案:

答案 0 :(得分:6)

1)因为语言规范是这样。

2)是:

  

每个“ if”,“ for”和“ switch”语句都被视为在其自身的隐式块中”

3)您确实在函数末尾返回了。不要使用命名的返回值。

答案 1 :(得分:2)

  

编译器可能会在“返回”中禁止使用空表达式列表   声明是否带有与之不同的实体(常量,类型或变量)   与结果参数同名的范围在   返回。

尝试在if范围内返回值,您将知道err变量在if范围内被遮盖。

func receive1() (err error) {
    if v, err := produce(); err != nil {
        fmt.Println("value2: ", v)
        return // err is shadowed during return
    }   
    return
}

以上代码将显示错误:

  

错误在返回期间被遮盖

Playground example

在第二个函数中,在return语句中声明的err分配了局部变量作用域:

// err is the return value. It's OK
func receive2() (err error) {
    v, err := produce()
    if err != nil {
        fmt.Println("value2: ", v)
        return
    }
    return
}

playground上尝试

如果函数的结果类型为其结果参数指定名称,则表达式列表可能为空。结果参数充当普通的局部变量,并且该函数可以根据需要为其分配值。 “ return”语句返回这些变量的值。

func complexF3() (re float64, im float64) {
    re = 7.0
    im = 4.0
    return
}
  

无论如何声明,所有结果值都是   在输入时将其类型初始化为零值   功能。指定结果的“ return”语句设置结果   参数在执行任何延迟函数之前。