satoru
satoru

Reputation: 33215

Getting and setting length of arbitrary slice

To get length of any slice, I use reflect.ValueOf(slice).Len(). To set length of any slice, I use reflect.ValueOf(&slice).Elem().SetLen(n).

I have a field of type reflect.Value in my struct, and the value is set to be reflect.ValueOf(&slice) so that I can change the slice. But now I can't get the length of the underlying slice.

It would panic because of call of reflect.Value.Len on ptr Value if I call Len() directly, and call of reflect.Value.Len on interface Value if I call Elem().Len().

Below is the function I was trying to implement:

func pop(slice interface{}) interface{} {
    v := reflect.ValueOf(slice)
    length := v.Len()
    last := v.Index(length - 1)
    v.SetLen(length - 1)
    return last
}

How can I do both with refect.Value of the slice pointer?

Upvotes: 2

Views: 934

Answers (1)

user12258482
user12258482

Reputation:

Write the function to work with a pointer to slice argument.

// pop removes and returns the last element from
// the slice pointed to by slicep.
func pop(slicep interface{}) interface{} {
    v := reflect.ValueOf(slicep).Elem()
    length := v.Len()
    last := v.Index(length - 1)
    v.SetLen(length - 1)
    return last
}

Call it like this:

slice := []int{1, 2, 3}
last := pop(&slice)
fmt.Println(last)  // prints 3
fmt.Println(slice) // prints [1 2]

Run it on the playground

Upvotes: 2

Related Questions