reflect.Value.MethodByName

Метод reflect.Value.MethodByName возвращает метод, привязанный к значению, по его имени. В первый параметр мы передаем имя метода в виде строки. Метод возвращает значение типа reflect.Value, которое представляет собой функцию. Если метод с указанным именем не найден, возвращается нулевое значение reflect.Value, проверить которое можно методом IsValid. Для успешного вызова полученного метода, его необходимо вызвать через метод Call, передав слайс аргументов.

Синтаксис

govalue.MethodByName(name)

Пример

Давайте получим метод структурного значения по имени и вызовем его с аргументом:

gopackage main

import (
  "fmt"
  "reflect"
)

type Person struct {
  Name string
  Age  int
}

func (p Person) Greet(greeting string) string {
  return fmt.Sprintf("%s, %s!", greeting, p.Name)
}

func main() {
  p := Person{Name: "Alice", Age: 30}
  v := reflect.ValueOf(p)

  method := v.MethodByName("Greet")
  if method.IsValid() {
    args := []reflect.Value{reflect.ValueOf("Hello")}
    res := method.Call(args)
    fmt.Println(res[0].Interface())
  }
}

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

go"Hello, Alice!"

Пример

Рассмотрим случай, когда метод с указанным именем не существует. В этом случае MethodByName возвращает невалидное значение:

gopackage main

import (
  "fmt"
  "reflect"
)

type Person struct {
  Name string
  Age  int
}

func (p Person) Greet(greeting string) string {
  return fmt.Sprintf("%s, %s!", greeting, p.Name)
}

func main() {
  p := Person{Name: "Bob", Age: 25}
  v := reflect.ValueOf(p)

  method := v.MethodByName("NonExistentMethod")
  if method.IsValid() {
    fmt.Println("Method found")
  } else {
    fmt.Println("Method not found")
  }
}

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

go"Method not found"

Пример

Метод MethodByName также может работать с методами, принимающими несколько аргументов и возвращающими несколько значений:

gopackage main

import (
  "fmt"
  "reflect"
)

type Calculator struct{}

func (c Calculator) Add(a, b int) (int, string) {
  sum := a + b
  return sum, fmt.Sprintf("Sum is %d", sum)
}

func main() {
  calc := Calculator{}
  v := reflect.ValueOf(calc)

  method := v.MethodByName("Add")
  if method.IsValid() {
    args := []reflect.Value{
      reflect.ValueOf(10),
      reflect.ValueOf(20),
    }
    res := method.Call(args)

    fmt.Println(res[0].Interface())
    fmt.Println(res[1].Interface())
  }
}

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

go30
"Sum is 30"

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

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