如何检查接口是否是指向切片的指针



我知道如何检查接口是否是指针:

func isPointerArray(i interface{}) bool {
if i == nil {
return false
}
if reflect.ValueOf(i).Kind() != reflect.Ptr {
return false
}
}

但是我该如何检查指针是否是切片呢?TypeOf是一个指针。

如果值的种类是reflect.Ptr,则可以使用Value.Elem()来获得指向的值,并且可以将其种类与reflect.Slice进行比较。

这就是它的样子:

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
}

但有一个问题。如果传递的值是指向切片类型的指针,但值本身是nil指针,则会报告false。这是可以理解的,因为没有一个类型可以是切片的点值。这可能是你想要的,也可能不是你想要的。

如果即使对于nil指针值(属于指针到切片类型)也需要true,则可以使用reflect.Type而不是reflect.Value。这也适用于nil指针,因为即使没有指针值,仍然有一个指针类型(称为基类型)。

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
}

测试上述功能:

vals := []interface{}{
nil,
"a",
&image.Point{},
[]string{},
&[]string{},
(*[]string)(nil),
}
for _, v := range vals {
fmt.Printf("%-14T isPtrSlice: %-5t, isPtrSlice2: %tn",
v, isPtrSlice(v), isPtrSlice2(v))
}

哪个将输出(在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

正如您在最后一行中看到的(其中值是*[]string类型的nil指针),isPtrSlice()返回false,而isPtrSlice2()返回true

您可以使用类型断言:

package main
import "fmt"
func main() {
var value interface{}
value = &[]int{1, 2}
if res, ok := value.(*[]int); ok {
fmt.Println(res)
}
}