Тип reflect.Method

Тип reflect.Method представляет собой структуру, которая содержит информацию о конкретном методе, полученную через пакет reflect. Этот тип используется для описания методов структуры или интерфейса. Структура reflect.Method содержит четыре поля: Name (имя метода), PkgPath (путь пакета, для экспортируемых методов пустой), Type (тип метода как reflect.Type) и Func (значение метода как reflect.Value).

Синтаксис

gotype Method struct {
  Name  string
  PkgPath string
  Type  Type
  Func  Value
}

Для получения информации о методах используются методы reflect.Type.NumMethod и reflect.Type.Method. Первый возвращает количество методов, второй - информацию о методе по индексу.

Пример получения информации о методах структуры

Давайте создадим структуру с методами и получим информацию о них с помощью рефлексии:

gopackage main

import (
  "fmt"
  "reflect"
)

type Person struct {
  Name string
  Age  int
}

func (p Person) Greet() string {
  return "Hello, " + p.Name
}

func (p Person) IsAdult() bool {
  return p.Age >= 18
}

func main() {
  p := Person{Name: "Alice", Age: 25}
  t := reflect.TypeOf(p)

  fmt.Println("Number of methods:", t.NumMethod())

  for i := 0; i < t.NumMethod(); i++ {
    method := t.Method(i)
    fmt.Printf("Method %d: %+v\n", i, method)
  }
}

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

go"Number of methods: 2"
"Method 0: {Name:Greet PkgPath: Type:func(main.Person) string Func:<func(main.Person) string Value>}"
"Method 1: {Name:IsAdult PkgPath: Type:func(main.Person) bool Func:<func(main.Person) bool Value>}"

Пример использования полей Method

Давайте продемонстрируем, как использовать поля reflect.Method для получения имени и типа метода, а также для вызова метода через рефлексию:

gopackage main

import (
  "fmt"
  "reflect"
)

type Calculator struct{}

func (c Calculator) Add(a, b int) int {
  return a + b
}

func (c Calculator) Multiply(a, b int) int {
  return a * b
}

func main() {
  calc := Calculator{}
  t := reflect.TypeOf(calc)

  for i := 0; i < t.NumMethod(); i++ {
    method := t.Method(i)
    fmt.Println("Method name:", method.Name)
    fmt.Println("Method type:", method.Type)

    // Вызов метода через рефлексию
    args := []reflect.Value{
      reflect.ValueOf(calc),
      reflect.ValueOf(5),
      reflect.ValueOf(3),
    }
    result := method.Func.Call(args)
    fmt.Println("Result:", result[0].Interface())
    fmt.Println("---")
  }
}

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

go"Method name: Add"
"Method type: func(main.Calculator, int, int) int"
"Result: 8"
"---"
"Method name: Multiply"
"Method type: func(main.Calculator, int, int) int"
"Result: 15"
"---"

Пример работы с экспортируемыми и неэкспортируемыми методами

Поле PkgPath в reflect.Method позволяет определить, является ли метод экспортируемым. Для экспортируемых методов это поле пустое:

gopackage main

import (
  "fmt"
  "reflect"
)

type Example struct{}

func (e Example) ExportedMethod() {}

func (e Example) unexportedMethod() {}

func main() {
  t := reflect.TypeOf(Example{})
  for i := 0; i < t.NumMethod(); i++ {
    m := t.Method(i)
    isExported := m.PkgPath == ""
    fmt.Printf("Method: %s, Exported: %t, PkgPath: %q\n",
      m.Name, isExported, m.PkgPath)
  }
}

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

go"Method: ExportedMethod, Exported: true, PkgPath: \"\""
"Method: unexportedMethod, Exported: false, PkgPath: \"main\""

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

  • тип reflect.Type,
    который предоставляет информацию о типах данных
  • тип reflect.Value,
    который представляет значения данных в рефлексии
  • функцию reflect.Type.Method,
    которая возвращает метод по индексу
  • функцию reflect.Type.NumMethod,
    которая возвращает количество методов