особенности golang — указателя

#go

#Вперед

Вопрос:

Нужна помощь в понимании того, почему это ломается. PrintFoo можно вызвать, используя либо указатель, либо значение. Почему не 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 := amp;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:

Из документации :

 // NumField returns the number of fields in the struct v.
// It panics if v's Kind is not Struct.
func (v Value) NumField() int
 

Вы вызываете его по указателю, вместо этого вы должны вызвать его в структуре, например :

 fmt.Println(reflect.Indirect(reflect.ValueOf(a)).NumField())
fmt.Println(reflect.Indirect(reflect.ValueOf(*a)).NumField())
 

Если вы не уверены, является ли ваше значение указателем или нет, используйте reflect .Косвенный:

Косвенный возвращает значение, на которое указывает v . Если v — нулевой указатель, Indirect возвращает нулевое значение. Если v не является указателем, косвенный возвращает v.

//править:

NumField вызывается Value , а не ваш фактический объект, например, вы делаете:

 func main() {
    a := amp;A{foo: "afoo"}
    fmt.Printf("%#vn", reflect.TypeOf(*a))
    fmt.Printf("%#vn", reflect.TypeOf(a))
}
 

Вы получите :

 //*a
amp;reflect.rtype{size:0x8, ...... ptrToThis:(*reflect.rtype)(0xec320)} 
//a
amp;reflect.rtype{size:0x4, ...... ptrToThis:(*reflect.rtype)(nil)}
 

Как вы можете сказать, это совершенно другой зверь.

  • Первый содержит информацию об указателе, следовательно ptrToThis , указывает на фактическую структуру.
  • Второй содержит информацию о самой структуре.

Комментарии:

1. >> «Вы вызываете его по указателю, вместо этого вы должны вызывать его в структуре» — Но я смог вызвать PrintFoo с помощью pointer или struct . Это сработало в любом случае. Почему не с NumField меня сбило с толку.

2. Вы не вызываете NumField a , вы вызываете его, несмотря ни на type Value struct{} что, ваш a может быть float или string , но пока это не «прямая» структура, это приведет к ошибке.

3. Добавьте больше информации, я надеюсь, это поможет.