dongpalou5352 2014-06-20 22:26
浏览 12
已采纳

golang-指针特质

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条回答 默认 最新

  • doubi1624 2014-06-20 22:33
    关注

    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
    ", reflect.TypeOf(*a))
        fmt.Printf("%#v
    ", 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.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?