Below code causes runtime panic on second Println if assertion fails and second value "OK" is not provided for assignment for return value. however, if the second value is provided runtime panic does not occur. How not assigning return value can cause the panic? is there any good resource to learn about panics in Go?
var i interface{} = "hello"
f, ok := i.(float64) // no runtime panic
fmt.Println(f, ok)
f = i.(float64) // panic
fmt.Println(f)
Update 1: To make the question more clear. I wanted to know how panic occurs at runtime when the second return value is not caught 'ok' and panic does not occur when the second return value is caught (f is assigned to zero value and ok is false)
Update 2: From the discussion I understood, assigning two return values handles the runtime panic, in short, it acts as a safeguard. Marking the answer as correct.
This is how type assertions are defined to work, nothing shocking about that.
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.
In your case i
holds a dynamic value of type string
, and yet you try to type-assert a value of float64
from it. So the type assertion is false, and per spec a run-time panic occurs. If you'd write i.(string)
=> this type assertion is true, so no run-time panic would occur in this case.
If you use the special form (assigning 2 return values), it will never panic, rather if type assertion does not hold, first value will be the zero value of the type you try to assert, second value will be an untyped boolean value false
.
You can use an underscore for variables you don't need.
var i interface{} = "hello"
f, ok := i.(float64) // no runtime panic
fmt.Println(f, ok)
f, _ = i.(float64) // panic
fmt.Println(f)