为啥在 Go 中将指针放入 interface 会导致反射丢失类型的名称?
Posted
技术标签:
【中文标题】为啥在 Go 中将指针放入 interface 会导致反射丢失类型的名称?【英文标题】:Why does putting a pointer in an interface in Go cause reflect to lose the name of the type?为什么在 Go 中将指针放入 interface 会导致反射丢失类型的名称? 【发布时间】:2015-04-04 23:47:48 【问题描述】:下面的示例显示了当您反映设置为对象 (g) 和指向该对象 (h) 的指针的接口 时会发生什么。这是设计使然,我应该期望我的数据类型丢失还是当我将指针放在接口 中时我无法取回数据类型的名称?
包主 导入“fmt” 导入“反射” 类型 Foo 结构 条弦 功能主要() f := FooBar: "FooBar" typeName := reflect.TypeOf(f).Name() fmt.Printf("typeName %v\n", typeName) 变量 g 接口 g = f typeName = reflect.TypeOf(g).Name() fmt.Printf("typeName %v\n", typeName) var h 接口 h = &f typeName = reflect.TypeOf(h).Name() fmt.Printf("typeName %v\n", typeName)输出:
类型名称 Foo 类型名称 Foo 类型名称也位于:
http://play.golang.org/p/2QuBoDxHfX
【问题讨论】:
【参考方案1】:正如Name
方法的文档所说,未命名的类型将返回一个空字符串:
Name
在其包中返回类型的名称。 它为未命名的类型返回一个空字符串。
h
的类型是一个未命名的指针类型,它的元素类型是命名的struct类型Foo
:
v := reflect.TypeOf(h)
fmt.Println(v.Elem().Name()) // prints "Foo"
如果您想要这样的复杂未命名类型的标识符,请使用String
方法:
fmt.Println(v.String()) // prints "*main.Foo"
【讨论】:
谢谢!。非常有意思。阅读 Elem() 上的文档有点令人困惑。 // Elem 返回一个类型的元素类型。 // 如果类型的 Kind 不是 Array、Chan、Map、Ptr 或 Slice,它会发生混乱。 Elem() 类型。所以,reflect.TypeOf 返回一个 Type,Elem 返回一个 elements Type。 “元素”是我所反映的价值吗? 另外,似乎 Elem() 没有恐慌的唯一原因是因为包含的类型是一个指针。我觉得有趣的是 Elem().Name() 然后返回“Foo”而不是 *Foo。 @Nate:Elem
这个名字对于指针来说有点误导,但对于其他类型来说是完全合理的。例如。如果您考虑[]int
,Elem()
方法会为您提供切片元素的类型,这里是 int(而不是 []int)。相同的逻辑适用于指针:您反映指针类型,Elem()
为您提供“指针类型的元素”的类型,并且 Name 显然是“Foo”而不是“*Foo”作为元素的名称[]int 是 int 而不是 []int。
不管怎样,h
的类型是interface
,而不是指针类型。 h
的 值 具有(未命名的)指针类型。如果您将&h
传递给reflect.TypeOf
而不是h
,这将变得很明显。但是,在 Go 中,接口(大部分)是按值传递的,reflect.TypeOf
采用 interface
,因此如果按值传递,它无法知道 h
的类型。这种区别在这里不是很重要,但如果h
有一个命名接口类型,如io.Reader
,就会更加明显。以上是关于为啥在 Go 中将指针放入 interface 会导致反射丢失类型的名称?的主要内容,如果未能解决你的问题,请参考以下文章