如果断言失败,下面的代码会导致第二个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:从我理解的讨论中,分配两个返回值可以处理运行时的恐慌,简而言之,它可以起到安全保障的作用。将答案标记为正确。
答案 0 :(得分:3)
这就是类型断言被定义为有效的方式,没有什么令人震惊的。
Language Spec: Type assertions:
对于interface type的
x
和T
类型的表达式,主要表达式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
。否则为false
,v
的值为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)