未捕获类型断言中的第二个 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
.
如果断言失败并且未提供第二个值 "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 typeT
, the primary expressionx.(T)
asserts that
x
is notnil
and that the value stored inx
is of typeT
. The notationx.(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 isT
. 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
istrue
if the assertion holds. Otherwise it isfalse
and the value ofv
is the zero value for typeT
. No run-time panic occurs in this case.
在您的例子中,i
拥有一个类型为 string
的动态值,但您尝试从中 type-assert 一个 float64
的值。所以类型断言是错误的,并且根据规范会发生 run-time 恐慌。如果您编写 i.(string)
=> 此类型断言为真,那么在这种情况下不会发生 run-time 恐慌。
如果你使用特殊形式(分配 2 return 值),它永远不会恐慌,而是如果类型断言不成立,第一个值将是你尝试断言的类型的零值,第二个值将是一个无类型的布尔值 false
.