在类型断言中没有捕获第二个返回值会导致运行时出现混乱

时间:2018-04-06 07:12:47

标签: go panic

如果断言失败,下面的代码会导致第二个Println运行时发生混乱,第二个值" OK"不提供返回值的分配。但是,如果提供第二个值,则不会发生运行时恐慌。如何不分配返回值会引起恐慌? Go有什么好的资源可以学习恐慌吗?

var i interface{} = "hello" 

    f, ok := i.(float64) //  no runtime panic
    fmt.Println(f, ok)

    f = i.(float64) // panic
    fmt.Println(f)

更新1:使问题更加清晰。 我想知道当第二个返回值没有被捕获时,运行时会出现什么样的恐慌' ok'捕获第二个返回值时不会发生混乱(f被赋值为零,ok为false)

更新2:从我理解的讨论中,分配两个返回值可以处理运行时的恐慌,简而言之,它可以起到安全保障的作用。将答案标记为正确。

2 个答案:

答案 0 :(得分:3)

这就是类型断言被定义为有效的方式,没有什么令人震惊的。

Language Spec: Type assertions:

  

对于interface typexT类型的表达式,主要表达式

x.(T)
     

断言x不是nil,而x中存储的值的类型为T。符号x.(T)称为类型断言

     

[...]如果类型断言成立,则表达式的值是存储在x中的值,其类型为T如果类型断言为false,则会出现run-time panic

     

[...] assignment中使用的类型断言或特殊形式的初始化

v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)
var v, ok T1 = x.(T)
     

产生一个额外的无类型布尔值。如果断言成立,则ok的值为true。否则为falsev的值为T类型的zero value在这种情况下不会发生运行时恐慌。

在您的情况下,i包含string类型的动态值,但您尝试从中键入 - float64的值。因此类型断言是错误的,并且根据规范发生运行时恐慌。如果你写i.(string) =>这种类型的断言是正确的,因此在这种情况下不会发生运行时恐慌。

如果使用特殊形式(分配2个返回值),它将永远不会出现恐慌,而不是类型断言不成立,第一个值将是您尝试断言的类型的零值,第二个值将是无类型布尔值false

答案 1 :(得分:0)

您可以使用下划线表示您不需要的变量。

var i interface{} = "hello" 

    f, ok := i.(float64) //  no runtime panic
    fmt.Println(f, ok)

    f, _ = i.(float64) // panic
    fmt.Println(f)