如何通过接口获取指针的值类型?

时间:2016-01-31 04:32:42

标签: go

playground说明了我的问题。

基本上我有一个接受空接口作为参数的函数。我想传递任何内容并打印有关类型和值的信息。

它按预期工作,除非我将指针传递给自定义类型(在我的示例中,基础结构类型)。我不完全确定反射模型在那时是如何构建的。由于函数签名在我调用interface{}时指定了reflect.Indirect(v).Kind()参数,它自然会返回interface但我想知道函数被调用时的类型。

以下是与游乐场相同的代码:

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var s interface{}
    s = CustomStruct{}

    PrintReflectionInfo(s)
    PrintReflectionInfo(&s)
}

type CustomStruct struct {}

func PrintReflectionInfo(v interface{}) {
    // expect CustomStruct if non pointer
    fmt.Println("Actual type is:", reflect.TypeOf(v))

    // expect struct if non pointer
    fmt.Println("Value type is:", reflect.ValueOf(v).Kind())

    if reflect.ValueOf(v).Kind() == reflect.Ptr {
        // expect: CustomStruct
        fmt.Println("Indirect type is:", reflect.Indirect(reflect.ValueOf(v)).Kind()) // prints interface

        // expect: struct
        fmt.Println("Indirect value type is:", reflect.Indirect(reflect.ValueOf(v)).Kind()) // prints interface
    }

    fmt.Println("")
}

2 个答案:

答案 0 :(得分:10)

要获取结构值,您需要获取界面值element

fmt.Println("Indirect type is:", reflect.Indirect(reflect.ValueOf(v)).Elem().Type()) // prints main.CustomStruct

fmt.Println("Indirect value type is:", reflect.Indirect(reflect.ValueOf(v)).Elem().Kind()) // prints struct

playground example

此代码有助于理解示例中的类型:

rv := reflect.ValueOf(v)
for rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Interface {
    fmt.Println(rv.Kind(), rv.Type())
    rv = rv.Elem()
}
fmt.Println(rv.Kind(), rv.Type())

&s的输出是:

ptr *interface {}
interface interface {}
struct main.CustomStruct

playground example

答案 1 :(得分:0)

使用reflect.Indirect

package main

import (
    "fmt"
    "reflect"
)

func testFunc(value interface{}) {
    fmt.Println("---------------------")
    fmt.Println("type = " + reflect.ValueOf(value).Type().String())
    fmt.Println("kind = " + reflect.ValueOf(value).Kind().String())
    if reflect.ValueOf(value).Kind() == reflect.Ptr {
        fmt.Println("--> pointer ")
        pointsToValue := reflect.Indirect(reflect.ValueOf(value))
        fmt.Println("-->", pointsToValue.Kind(), " - ", pointsToValue.Type(), " - ", pointsToValue)
        if pointsToValue.Kind() == reflect.Slice {
            fmt.Println("--> slice !! ")
        }
    }
}

func main() {
    var testVar1 string
    var testVar2 []string
    var testVar3 []*string
    testVar2 = append(testVar2, "A")
    testVar2 = append(testVar2, "B")
    testFunc(testVar1)
    testFunc(testVar2)
    testFunc(testVar3)
    testFunc(testVar2)
    testFunc(&testVar2)
}
/*
---------------------
type = string
kind = string
---------------------
type = []string
kind = slice
---------------------
type = []*string
kind = slice
---------------------
type = []string
kind = slice
---------------------
type = *[]string
kind = ptr
--> pointer 
--> slice  -  []string  -  [A B]
--> slice !!
*/

https://play.golang.org/p/ysqIWQYyzn3