Pointers 为什么在Go中的接口{}中放置指针会导致反射丢失类型的名称?

Pointers 为什么在Go中的接口{}中放置指针会导致反射丢失类型的名称?,pointers,reflection,go,Pointers,Reflection,Go,下面的示例显示了当您对设置为对象(g)的接口{}和指向所述对象(h)的指针进行反射时会发生什么。这是出于设计考虑的吗?当我将指针放在接口{}中时,我是否应该期望我的数据类型丢失,或者更确切地说,我无法获取数据类型的名称 package main import "fmt" import "reflect" type Foo struct { Bar string } func main() { f := Foo{Bar: "FooBar"} typeName := r

下面的示例显示了当您对设置为对象(g)的接口{}和指向所述对象(h)的指针进行反射时会发生什么。这是出于设计考虑的吗?当我将指针放在接口{}中时,我是否应该期望我的数据类型丢失,或者更确切地说,我无法获取数据类型的名称

package main import "fmt" import "reflect" type Foo struct { Bar string } func main() { f := Foo{Bar: "FooBar"} typeName := reflect.TypeOf(f).Name() fmt.Printf("typeName %v\n", typeName) var g interface{} g = f typeName = reflect.TypeOf(g).Name() fmt.Printf("typeName %v\n", typeName) var h interface{} h = &f typeName = reflect.TypeOf(h).Name() fmt.Printf("typeName %v\n", typeName) } 包干管 输入“fmt” 导入“反映” 类型Foo struct{ 棒串 } func main(){ f:=Foo{Bar:FooBar} typeName:=reflect.TypeOf(f).Name() fmt.Printf(“类型名%v\n”,类型名) var g接口{} g=f typeName=reflect.TypeOf(g).Name() fmt.Printf(“类型名%v\n”,类型名) var h接口{} h=&f typeName=reflect.TypeOf(h).Name() fmt.Printf(“类型名%v\n”,类型名) } 产出:

typeName Foo typeName Foo typeName 字体名Foo 字体名Foo 字体名 也在:


正如
Name
方法的文档所述,未命名类型将返回一个空字符串:

Name
返回其包中类型的名称。 它为未命名的类型返回一个空字符串

h
的类型是一种未命名的指针类型,其元素类型是命名的结构类型
Foo

v := reflect.TypeOf(h)
fmt.Println(v.Elem().Name()) // prints "Foo"
如果您想要这样的复杂未命名类型的标识符,请使用
String
方法:

fmt.Println(v.String()) // prints "*main.Foo"

谢谢真有趣。阅读Elem()上的文档有点混乱。//Elem返回类型的元素类型。//如果类型的种类不是数组、Chan、Map、Ptr或Slice,它就会恐慌。Elem()类型。因此,reflect.TypeOf返回一个类型,Elem返回一个元素类型。“element”是我要反映的值吗?而且,Elem()没有惊慌的唯一原因似乎是因为包含的类型是指针。我觉得很有趣,Elem().Name()然后返回“Foo”而不是*Foo。@Nate:Name
Elem
对于指针来说有点误读,但是对于其他类型来说它是完全合理的。例如,如果您对
[]int
进行反思,则
Elem()
方法会给出切片元素的类型,这里是int(而不是[]int)。同样的逻辑也适用于指针:您对指针类型进行反思,
Elem()
为您提供了“指针类型的元素”的类型,该名称显然是“Foo”而不是“*Foo”,因为[]int的元素名称是int而不是[]int。值得注意的是,
h
的类型是
interface{}
而不是指针类型。具有(未命名)指针类型的是
h
的值。如果您将
&h
传递到
reflect.TypeOf
而不是
h
,这一点就会变得明显。然而,接口在Go中(大部分)是通过值传递的,并且
反映.TypeOf
采用
接口{}
,因此如果通过值传递,它无法知道
h
的类型。这种区别在这里并不是特别重要,但如果
h
有一个命名的接口类型,如
io.Reader
,则会更加明显。