【问题标题】:How to check if interface is a a pointer to a slice如何检查接口是否是指向切片的指针
【发布时间】:2021-12-09 00:17:30
【问题描述】:

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

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

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

【问题讨论】:

    标签: go pointers reflection slice


    【解决方案1】:

    如果值的种类是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
    

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

    【讨论】:

    • 对于数组,可以使用reflect.Array,例如elem.Kind() == reflect.Slice || elem.Kind() == reflect.Array
    • 那里有一些 icza 质量响应。谢谢
    【解决方案2】:

    你可以使用type assertions:

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

    【讨论】:

    • 一个限制是我不知道类型。
    猜你喜欢
    • 1970-01-01
    • 2018-05-30
    • 2013-08-20
    • 2011-06-07
    • 2020-03-29
    • 1970-01-01
    • 2015-05-01
    • 2017-07-04
    相关资源
    最近更新 更多