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.