Confusion with pointer, slices and interface{} in function arguments in go

Viewed 440

I've been reading about how Go passes arguments to functions via pointer vs. value. I've been reading about the interface type. And I've been tampering with the reflect package. But clearly, I still don't understand how it all works because of this example code here:

package main

import (
  "reflect"
  "fmt"
)
type Business struct {
  Name string
}

func DoSomething(b []Business) {

  var i interface{}
  i = &b
  v := reflect.ValueOf(i).Elem()

  for c:=0 ;c<10; c++ {

    z := reflect.New(v.Type().Elem())
    s := reflect.ValueOf(z.Interface()).Elem()
    s.Field(0).SetString("Pizza Store "+ fmt.Sprintf("%v",c))
    v.Set(reflect.Append(v, z.Elem()))
  }
  fmt.Println(b)

}

func main() {

  business := []Business{}
  DoSomething(business)

}

When I run this code, it will print a list of ten Business structs with the Business.Name of Pizza 0 to 9. I understand that in my example, that my DoSomething function received a copy of the slice of business, and hence, the business variable in my main function remains unaffected by whatever DoSomething does.

What I did next was change my func DoSomething(b []Business) to func DoSomething(b interface{}). Now when I try to run my script, I get the run time error of panic: reflect: Elem of invalid type on on the line z := reflect.New(v.Type().Elem())

I noticed that with DoSomething(b []Business), the variable i == &[]. But with DoSomething(b interface{}), the variable i == 0xc42000e1d0. Why is the variable i different under these two circumstances?

1 Answers

Your debugger most likely uses (or at least follows) the default formatting rules of the fmt package:

For compound objects, the elements are printed using these rules, recursively, laid out like this:

struct:             {field0 field1 ...}
array, slice:       [elem0 elem1 ...]
maps:               map[key1:value1 key2:value2 ...]
pointer to above:   &{}, &[], &map[]

In your first case i holds a value of type *[]Business. So if a value being printed (or inspected) is a pointer to slice, it is printed as &[values].

In your second case i holds a pointer to an interface{} value, which is of type *interface{}. When printing a value of this type, the default %p format is used which simply prints the memory address as a hexadecimal value prefixed with 0x.

Related