It isn't that surprise once we know that the interface internal structure
contains 2 words. In the below case, explodes interface has a saving to *Bomb, which is nil,
but the interface itself isn't nil, which contains *Bomb.
type Explodes interface {
Bang()
Boom()
}
// Type Bomb implements Explodes
type Bomb struct {}
func (*Bomb) Bang() {}
func (Bomb) Boom() {}
func main() {
var bomb *Bomb = nil
var explodes Explodes = bomb
println(bomb, explodes) // '0x0 (0x10a7060,0x0)'
if explodes != nil {
println("Not nil!") // 'Not nil!' What are we doing here?!?!
explodes.Bang() // works fine
explodes.Boom() // panic: value method main.Bomb.Boom called using nil *Bomb pointer
} else {
println("nil!") // why don't we end up here?
}
}
Use reflect to check interface's underlying value is nil or not:
if explodes != nil && !reflect.ValueOf(explodes).IsNil() {
println("Not nil!") // we no more end up here
explodes.Bang()
explodes.Boom()
} else {
println("nil!") // 'nil' -- all good!
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.