英文:
golang - Pointer idiosyncrasies
问题
需要帮助理解为什么这段代码会出错。PrintFoo可以使用指针或值来调用。为什么NumField不行?
type A struct {
foo string
}
func (a *A) PrintFoo(){
fmt.Println("Foo value is " + a.foo)
}
func main() {
a := &A{foo: "afoo"}
(*a).PrintFoo() //可以正常工作
a.PrintFoo() //可以正常工作
reflect.TypeOf(*a).NumField() //可以正常工作 - Type = main.A
reflect.TypeOf(a).NumField() //出错!- Type = *main.A
}
链接:http://play.golang.org/p/Kw16ReujRx
英文:
Need help understanding why this breaks. PrintFoo can be called using either pointer or value. Why not NumField?
http://play.golang.org/p/Kw16ReujRx
type A struct {
foo string
}
func (a *A) PrintFoo(){
fmt.Println("Foo value is " + a.foo)
}
func main() {
a := &A{foo: "afoo"}
(*a).PrintFoo() //Works - no problem
a.PrintFoo() //Works - no problem
reflect.TypeOf(*a).NumField() //Works - no problem - Type = main.A
reflect.TypeOf(a).NumField() //BREAKS! - Type = *main.A
}
答案1
得分: 5
根据文档:
// NumField 返回结构体 v 中的字段数量。
// 如果 v 的类型不是 Struct,会引发 panic。
func (v Value) NumField() int
你正在对一个指针进行调用,你需要对一个结构体进行调用,例如示例:
fmt.Println(reflect.Indirect(reflect.ValueOf(a)).NumField())
fmt.Println(reflect.Indirect(reflect.ValueOf(*a)).NumField())
当你不确定你的值是指针还是其他类型时,可以使用reflect.Indirect:
Indirect 返回 v 指向的值。如果 v 是一个空指针,Indirect 返回一个零值。如果 v 不是指针,Indirect 返回 v。
//编辑:
NumField
是在 Value
上调用的,而不是你的实际对象,例如如果你这样做:
func main() {
a := &A{foo: "afoo"}
fmt.Printf("%#v\n", reflect.TypeOf(*a))
fmt.Printf("%#v\n", reflect.TypeOf(a))
}
你会得到:
//*a
&reflect.rtype{size:0x8, ...... ptrToThis:(*reflect.rtype)(0xec320)}
//a
&reflect.rtype{size:0x4, ...... ptrToThis:(*reflect.rtype)(nil)}
可以看出,它们是完全不同的。
- 第一个持有指针的信息,因此
ptrToThis
指向实际的结构体。 - 第二个持有结构体本身的信息。
英文:
From the documentation :
// NumField returns the number of fields in the struct v.
// It panics if v's Kind is not Struct.
func (v Value) NumField() int
You are calling it on a pointer, you have to call it on a struct instead, for example :
fmt.Println(reflect.Indirect(reflect.ValueOf(a)).NumField())
fmt.Println(reflect.Indirect(reflect.ValueOf(*a)).NumField())
When you're not sure if your value is a pointer or not, use reflect.Indirect:
> Indirect returns the value that v points to. If v is a nil pointer,
> Indirect returns a zero Value. If v is not a pointer, Indirect returns
> v.
//edit:
NumField
gets called on Value
, not your actual object, for example of you do:
func main() {
a := &A{foo: "afoo"}
fmt.Printf("%#v\n", reflect.TypeOf(*a))
fmt.Printf("%#v\n", reflect.TypeOf(a))
}
You will get :
//*a
&reflect.rtype{size:0x8, ...... ptrToThis:(*reflect.rtype)(0xec320)}
//a
&reflect.rtype{size:0x4, ...... ptrToThis:(*reflect.rtype)(nil)}
As you can tell, it's a completely different beast.
- The first one holds information about the pointer, hence
ptrToThis
points to the actual struct. - The second holds info about the struct itself.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论