英文:
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
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 {}
答案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 !!
*/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论