What is the nil interface's pointer?


(Xu Walter) #1

Hi all:
After reading some books about golang learning,I conclude that the ‘nil’ means ‘declared but has not allocate any memory’ when you declare some reference types,so when you print the pointer of these type’s zero value,the pointer should be 0x0:

	var m1 map[int]string

	if m1 == nil {
		fmt.Printf("type of m1: %T \t addr of m1: %p \n", m1, m1)
	}

	var m2 []int

	if m2 == nil {
		fmt.Printf("type of m2: %T \t addr of m2: %p \n", m2, m2)
	}

	var m3 *int 

	if m3 == nil {
		fmt.Printf("type of m3: %T \t addr of m3: %p \n", m3, m3)
	}

	var m4 interface {
		foobar() int
	}

	if m4 == nil {
		fmt.Printf("type of m4: %T \t addr of m4: %p \n", m4, m4)
	}

	var m5 chan int

	if m5 == nil {
		fmt.Printf("type of m5: %T \t addr of m5: %p \n", m5, m5)
	}

	var m6 func(t string)
	if m6 == nil {
		fmt.Printf("type of m6: %T \t addr of m6: %p \n", m6, m6)
	}

	// output:
	// type of m1: map[int]string 	 addr of m1: 0x0 
	// type of m2: []int 	 addr of m2: 0x0 
	// type of m3: *int 	 addr of m3: 0x0 
	// type of m4: <nil> 	 addr of m4: %!p(<nil>) 
	// type of m5: chan int 	 addr of m5: 0x0 
	// type of m6: func(string) 	 addr of m6: 0x0 
 

As you can see,I have tested all the 6 kinds of reference types in golang,and 5 types support my conclusion of checking nil value,but the interface type not. I cannot print its pointer. How can I do or why golang prevent me from printing it?


(Ingo Krabbe) #2

As you can see from the output, m4 does not even has a type, yet. You can think of the interface type as a second level type. An interface gets its type after it has been assigned.
It might be possible to find the memory location for var m4 through unsafe.Pointer but I never tried!


(Xu Walter) #3

Thanks for reply.
Now I have two ways to print the memory location of m4:

	var m4 interface {
		foobar() int
	}

	if m4 == nil {
		fmt.Printf("way1: addr of m4: %p \n", unsafe.Pointer(&m4))
		fmt.Printf("way2: addr of m4: %v \n", reflect.ValueOf(&m4).Elem().Addr())
	}
//output
//way1: addr of m4: 0xc0000541c0 
//way2: addr of m4: 0xc0000541c0

They both point to the same address,does it means when declare an interface type ,golang will preallocate memory for it? Maybe it’s an opaque but meaningless problem,I’m just curious about it.


(Ingo Krabbe) #4

There might be a bit of memory allocated during compilation, but I doubt that there is any of that left at run time, but possibly a bit of type information, if that is used somewhere.
Interface types are used to guarantee behavior of values. When writing some code, we often are not directly interested in the value of an object, but in some behavior.
For example if we have a unix file descriptor var int fd = 0, in this case of STDIN, we are rarely interested in the value 0 for the input channel, but we want to read from it.
We can now call the read system call with that value and read from the channel.

But actually we can also write a function that reads from anything that defines the io.Reader interface and we even can make int value an io.Reader

func (fd int) Read(buf []bytes) (n int, err error) {
    /* some implementation details */
}

with this Read function

var x int
var y io.Reader

y = x

makes sense and y and x do actually have the type and value of same object, but stored in two different variables.

The value of &x or &m4 in your example just shows the location where that value is stored. So &x and &y are different, because we have two variables, but y = x and of course y == x is true also.

Of course the compiler checks on y = x if x implements the io.Reader interface, but it does not preallocate anything. y will have the same type and value as x after y = x but it will have no type and no value before it is assigned anything.


(Xu Walter) #5

Yep,I have realized that the interface type is a very special type, and your interpretation really make sense.Thanks !
I spent a lot of time to study the nil value, it’s really confusing to me compared with other similar type in other languages.It’s a bit regretful for not able to describe ‘nil value of reference types’ as: declared but has not allocate any memory, just one exception,the interface type.