5

I receive an interface which is basically a slice. Now I want to convert it to a pointer to the slice. The problem is, that I have either the slice itself or a Pointer to an interface. I can easily show in a code example:

func main(){ model := []int{1,2,3,4,5,6,7,8,10,11,133123123123} method(model) } func method(model interface{}){ fmt.Println(reflect.TypeOf(model)) // this is of type []int fmt.Println(reflect.TypeOf(&model)) // this is of type *interface{} } 

What I need is this type:

fmt.Println(reflect.TypeOf(result)) // this should be type *[]int 

I know the type only on runtime, therefore I cannot just take &(model.([]int))

Is there a way using golang reflection to receive this? the type 'int' is here actually not important, important is, that it is a Pointer to a slice. *[]interface{} would be okay either.

Edit:
To make the question more clear, I should have added: I am not interested in the data of the slice, but only in getting a pointer to a slice of same type (which can basically be empty). Therefore James Henstridge answers works perfectly.

4
  • What's wrong with golang.org/pkg/reflect/#Value.Addr ? I admit I do not understand what you really want to do. It really depends. Not all values in Go are addressable, so it might be impossible to do. What do you want to do with a *[]int? Commented Nov 3, 2014 at 21:21
  • Indeed this value is not addressable. Basically I want to create a slice of the predefined type (using reflect.MakeSlice) and pass it to a method of the library mgo (mgo's Query's All() method). This method needs a Ptr to Slice. I found a solution by creating the slice outside where type is known. But I'm trying to find a way to do this in a generic way inside. Do I understand you right, that since it is not an addressable value, it is not possible to do this? Commented Nov 3, 2014 at 21:36
  • everything in go is passed by value. You can't get a pointer to model after you copied the value into the method call. It doesn't matter that it's an interface{} or not, you have slice value, not a pointer. Commented Nov 3, 2014 at 22:54
  • 1
    To add to JimB's comment, slices act like pointers in that they reference some block of memory and changing an element of the slice changes the memory so you see it in your caller, but the slice variable itself cannot change because THAT is passed as a value. The slice variable contains a pointer to the underlying memory and the length and capacity of the slice. Commented Nov 4, 2014 at 0:23

1 Answer 1

6

Before trying to answer the question, it is worth stepping back and asking what the *[]int value you're after should point at?

Given the way method is called we can't possibly get a pointer to the model variable from the calling context, since it will only receive a copy of the slice as its argument (note that this is a copy of the slice header: the backing array is shared).

We also can't get a pointer to the copy passed as an argument since it is stored as an interface{} variable: the interface variable owns the memory used to store its dynamic value, and is free to reuse it when the a new value is assigned to it. If you could take a pointer to the dynamic value, this would break type safety if a different type is assigned.

We can obtain a *[]int pointer if we make a third copy of the slice, but it isn't clear whether that's what you'd necessarily want either:

v := reflect.New(reflect.TypeOf(model)) v.Elem().Set(reflect.ValueOf(model)) result := v.Interface() 

This is essentially a type agnostic way of writing the following:

v := new([]int) *v = model var result interface{} = v 

Now if you really wanted a pointer to the slice variable in the calling context, you will need to ensure that method is called with a pointer to the slice instead and act accordingly.

Sign up to request clarification or add additional context in comments.

2 Comments

This is a great use of the reflect package.
Thanks, this works perfectly! I am basically not interested in the content of the slice's array (it is always empty in my use-case), but only in getting a slice of same type and a pointer to it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.