未捕获类型断言中的第二个 return 值导致运行时恐慌

Not catching second return value in type assertion causes runtime panic

如果断言失败并且未提供第二个值 "OK" 以分配给 return 值,则以下代码会导致第二个 Println 出现运行时恐慌。但是,如果提供了第二个值,则不会发生运行时恐慌。为什么不分配 return 值会导致恐慌?有什么好的资源可以了解 Go 中的恐慌吗?

var i interface{} = "hello" 

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

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

更新1:使问题更清楚。 我想知道当第二个 return 值未被捕获 'ok' 时在运行时如何发生恐慌,而当第二个 return 值被捕获时(f 被分配为零值并且好的是假的)

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

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

var i interface{} = "hello" 

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

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

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

类型断言就是这样定义的,没什么好惊讶的。

Language Spec: Type assertions:

For an expression x of interface type and a type T, the primary expression

x.(T)

asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion.

[...] If the type assertion holds, the value of the expression is the value stored in x and its type is T. If the type assertion is false, a run-time panic occurs.

[...] A type assertion used in an assignment or initialization of the special form

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

yields an additional untyped boolean value. The value of ok is true if the assertion holds. Otherwise it is false and the value of v is the zero value for type T. No run-time panic occurs in this case.

在您的例子中,i 拥有一个类型为 string 的动态值,但您尝试从中 type-assert 一个 float64 的值。所以类型断言是错误的,并且根据规范会发生 run-time 恐慌。如果您编写 i.(string) => 此类型断言为真,那么在这种情况下不会发生 run-time 恐慌。

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