Search code examples
pointersgoslicereflect

`reflect.Kind()` of Slice Becomes `Struct` When Stored Inside Pointer


When checking the reflect.Kind() of a slice, reflect correctly identifies it as a slice when not stored inside a pointer:

package main

import (
    "fmt"
    "reflect"
)

type Dog struct {
    Name string
    Age  int
}

func main() {
    var dogs []Dog
    rDogs := reflect.ValueOf(dogs)
    fmt.Println(rDogs.Kind())
}

Output:

slice

However, when a slice is stored inside a pointer, reflect.Kind() identifies it as a struct:

package main

import (
    "fmt"
    "reflect"
)

type Dog struct {
    Name string
    Age  int
}

func main() {
    dogs1 := make([]Dog, 0)
    pointer := &dogs1
    printPointerValueKind(pointer)        

    var dogs2 []Dog
    pointer = &dogs2
    printPointerValueKind(pointer)
}

func printPointerValueKind(pointer interface{}) {
    if pointer != nil {
        rPointer := reflect.ValueOf(pointer)

        if rPointer.Kind() == reflect.Ptr {
            value := rPointer.Elem()
            rValue := reflect.ValueOf(value)
            fmt.Println(rValue.Kind())
        }
    }
}       

Output:

struct
struct

My questions are:

  1. Why does this happen?

  2. Is there a way to store a slice inside a pointer and still have reflect.Kind() identify it as a slice?


Solution

  • 1. (reflect.Value).Elem() returns a reflect.Value, which is a struct, and which does not need to be passed to reflect.ValueOf again if you're looking for the kind of the type that the value holds.

    2. rPointer.Elem().Kind() should be enough for what you need.