I know how to check if an interface is a pointer:
func isPointerArray(i interface{}) bool {
if i == nil {
return false
}
if reflect.ValueOf(i).Kind() != reflect.Ptr {
return false
}
}
But how can I check if that pointer is a slice? TypeOf
is a pointer.
CodePudding user response:
If the value's kind is reflect.Ptr
, you may use Value.Elem()
to get the pointed value, and you may compare its kind to reflect.Slice
.
This is how it would look like:
func isPtrSlice(i interface{}) bool {
if i == nil {
return false
}
v := reflect.ValueOf(i)
if v.Kind() != reflect.Ptr {
return false
}
return v.Elem().Kind() == reflect.Slice
}
But there's one catch though. If the value passed is a pointer to slice type but the value itself is the nil
pointer, this will report false
. Understandable, as there is no pointed value whose type could be a slice. This may or may not be what you want.
If you want true
even for nil
pointer values (that are of pointer to slice types), you may use reflect.Type
instead of reflect.Value
. This works for nil
pointers too, because even though there is no pointed value, there is still a pointed type (called the base type).
func isPtrSlice2(i interface{}) bool {
if i == nil {
return false
}
t := reflect.TypeOf(i)
if t.Kind() != reflect.Ptr {
return false
}
return t.Elem().Kind() == reflect.Slice
}
Testing the above functions:
vals := []interface{}{
nil,
"a",
&image.Point{},
[]string{},
&[]string{},
(*[]string)(nil),
}
for _, v := range vals {
fmt.Printf("%-14T isPtrSlice: %-5t, isPtrSlice2: %t\n",
v, isPtrSlice(v), isPtrSlice2(v))
}
Which will output (try it on the Go Playground):
<nil> isPtrSlice: false, isPtrSlice2: false
string isPtrSlice: false, isPtrSlice2: false
*image.Point isPtrSlice: false, isPtrSlice2: false
[]string isPtrSlice: false, isPtrSlice2: false
*[]string isPtrSlice: true , isPtrSlice2: true
*[]string isPtrSlice: false, isPtrSlice2: true
As you can see in the last line (where the value is a nil
pointer of type *[]string
) isPtrSlice()
returns false
while isPtrSlice2()
returns true
.
CodePudding user response:
You can use type assertions:
package main
import "fmt"
func main() {
var value interface{}
value = &[]int{1, 2}
if res, ok := value.(*[]int); ok {
fmt.Println(res)
}
}