Метод reflect.Type.NumField

Метод NumField принадлежит типу reflect.Type и возвращает количество полей структуры. Он применяется исключительно к структурным типам; при вызове на других типах возникает паника. Метод часто используется в сочетании с Field для итерации по всем полям структуры во время выполнения программы.

Синтаксис

gonumFields := t.NumField()

где t - переменная типа reflect.Type, представляющая структурный тип.

Пример

Давайте получим количество полей простой структуры:

gopackage main

import (
  "fmt"
  "reflect"
)

type Person struct {
  Name string
  Age  int
}

func main() {
  var p Person
  t := reflect.TypeOf(p)
  numFields := t.NumField()
  fmt.Println(numFields)
}

Результат выполнения кода:

go2

Пример

Давайте используем NumField для итерации по всем полям структуры с выводом их имен и типов:

gopackage main

import (
  "fmt"
  "reflect"
)

type Config struct {
  Host string
  Port int
  SSL  bool
}

func main() {
  var cfg Config
  t := reflect.TypeOf(cfg)
  
  for i := 0; i < t.NumField(); i++ {
    field := t.Field(i)
    fmt.Printf("Field %d: name=%s, type=%s\n", i, field.Name, field.Type)
  }
}

Результат выполнения кода:

go"Field 0: name=Host, type=string"
"Field 1: name=Port, type=int"
"Field 2: name=SSL, type=bool"

Пример

Рассмотрим пример с вложенными структурами и анонимными полями:

gopackage main

import (
  "fmt"
  "reflect"
)

type Address struct {
  City  string
  Index int
}

type User struct {
  ID    int
  Name  string
  Address Address
}

func main() {
  var u User
  t := reflect.TypeOf(u)
  fmt.Println("Total fields:", t.NumField())
  
  for i := 0; i < t.NumField(); i++ {
    field := t.Field(i)
    fmt.Printf("Field %d: %s (%s)\n", i, field.Name, field.Type)
  }
}

Результат выполнения кода:

go"Total fields: 3"
"Field 0: ID (int)"
"Field 1: Name (string)"
"Field 2: Address (main.Address)"

Пример

Давайте рассмотрим ситуацию, когда NumField вызывается на типе, не являющемся структурой:

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  var s string
  t := reflect.TypeOf(s)
  
  defer func() {
    if r := recover(); r != nil {
      fmt.Println("Panic:", r)
    }
  }()
  
  numFields := t.NumField()
  fmt.Println(numFields)
}

Результат выполнения кода:

go"Panic: reflect: NumField of non-struct type string"

Как видите, вызов NumField на строке вызывает панику, поэтому необходимо предварительно проверять тип с помощью метода Kind.

Смотрите также

  • метод reflect.Type,
    предоставляющий информацию о типе во время выполнения
  • метод reflect.Type.Field,
    возвращающий информацию о конкретном поле структуры
  • метод reflect.Type.Kind,
    позволяющий определить базовый вид типа перед вызовом NumField
  • функцию reflect.TypeOf,
    получающую тип значения для последующего использования