why does assigning interface with pointer and then an address shows different behaviour in Golang

-2

I'm new to golang. I'm starting with a tour of go. Here is the go playground link

Here is the code :

package main

import "fmt"

type I interface {
    M()
}

type T struct {
    S string
}

func (t *T) M() {

    fmt.Println(t.S)
}

func main() {
    var i I

    var t *T 
    i = t

    i.M()
}

It is panicing

panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0xd3ea6] goroutine 1 [running]: main.(*T).M(0x0, 0x434070) /tmp/sandbox696069628/main.go:15 +0x26 main.main() /tmp/sandbox696069628/main.go:24 +0x40

However when I change

var t *T 
i = t

to

var t T 
i = &t

It does not panic anymore

Shouldn't the behavior be similar in both cases. If not, why?

go
asked on Stack Overflow Dec 11, 2018 by topenion • edited Dec 11, 2018 by saddam

2 Answers

3

You are declaring, but not explicitly defining a variable named t in both cases. If you don't specify a value, the zero value for the variable's type is assigned

The zero value for all pointer types, including *T is nil. The zero value for a struct type is a value of that struct with all fields set to their zero values.

When storage is allocated for a variable [...] and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for numeric types, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.

https://golang.org/ref/spec#The_zero_value

Consequently this stores nil in the interface value i:

var i interface{ M() }
var t *T 
i = t
// i stores nil

And this stores a struct value in the interface value i:

var i interface{ M() }
var t T 
i = t
// i stores T{S:""}

So in the first case, (nil).M() is called (which panics), and in the second case (T{}).M() is called.

answered on Stack Overflow Dec 11, 2018 by Peter
2

You didn't initialized T.
Do this :

var t *T = &T{"Hello World"}
answered on Stack Overflow Dec 11, 2018 by Mostafa Solati

User contributions licensed under CC BY-SA 3.0