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

How to check if interface is a a pointer to a slice

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

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

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

您可以使用 type assertions:

package main

import "fmt"

func main() {
    var value interface{}
    value = &[]int{1, 2}

    if res, ok := value.(*[]int); ok {
        fmt.Println(res)
    }
}

如果值的种类是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。可以理解,因为没有类型可以是切片的指向值。这可能是也可能不是您想要的。

如果您想要 true 甚至 nil 指针值(指向切片类型的指针),您可以使用 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: %t\n",
        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() returns false while isPtrSlice2() returns true.