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

huangapple go评论85阅读模式
英文:

How to get the value type of a pointer through an interface?

问题

这个playground展示了我的问题。

基本上,我有一个接受空接口作为参数的函数。我想传入任何东西并打印类型和值的信息。

它按预期工作,除了当我传递一个指向自定义类型的指针时(在我的示例中,是底层结构类型)。我不太确定反射模型在那一点上是如何构造的。由于函数签名在调用reflect.Indirect(v).Kind()时指定了一个interface{}参数,它自然返回interface,但我想知道在调用函数时的类型。

以下是来自playground的相同代码:

package main

import (
	"fmt"
	"reflect"
)

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

	PrintReflectionInfo(s)
	PrintReflectionInfo(&s)
}

type CustomStruct struct {}

func PrintReflectionInfo(v interface{}) {
	// 非指针时期望CustomStruct
	fmt.Println("实际类型是:", reflect.TypeOf(v))

	// 非指针时期望struct
	fmt.Println("值类型是:", reflect.ValueOf(v).Kind())

	if reflect.ValueOf(v).Kind() == reflect.Ptr {
		// 期望: CustomStruct
		fmt.Println("间接类型是:", reflect.Indirect(reflect.ValueOf(v)).Kind()) // 打印interface

		// 期望: struct
		fmt.Println("间接值类型是:", reflect.Indirect(reflect.ValueOf(v)).Kind()) // 打印interface
	}

	fmt.Println("")
}
英文:

This playground illustrates my question.

Basically I have a function that accepts an empty interface as argument. I want to pass anything in and print information on the types and values.

It works as expected except when I pass a pointer to a custom type (in my example, of underlying struct type). I am not entirely sure how the reflection model is structured at that point. Since the function signature specifies an interface{} argument when I call reflect.Indirect(v).Kind() it naturally returns interface but I want to know the type when the function is called.

Below is the same code from playground:

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("")
}

答案1

得分: 24

要获取结构体的值,您需要获取接口值的元素。以下是示例代码:

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

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

您可以使用此代码来理解示例中的类型:

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

对于 &s 的输出是:

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

希望对您有所帮助!

英文:

To get the struct value, you need to get the interface value's 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

This code is helpful for understanding the types in the example:

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

The output for &s is:

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

playground example

答案2

得分: 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

英文:

use 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

huangapple
  • 本文由 发表于 2016年1月31日 12:32:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/35110366.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定