Jul 13, 2018

[Go] nil for interface

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.