Метод reflect.Value.Call

Метод reflect.Value.Call вызывает функцию, представленную объектом reflect.Value. В первый параметр мы передаем слайс аргументов типа []reflect.Value, которые будут переданы вызываемой функции. Метод возвращает слайс []reflect.Value с результатами выполнения функции. Если функция не возвращает значений, возвращается пустой слайс.

Синтаксис

gofunc (v Value) Call(in []Value) []Value

Пример

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

gopackage main

import (
  "fmt"
  "reflect"
)

func add(a, b int) int {
  return a + b
}

func main() {
  fn := reflect.ValueOf(add)
  args := []reflect.Value{
    reflect.ValueOf(10),
    reflect.ValueOf(20),
  }
  res := fn.Call(args)
  fmt.Println(res[0].Int())
}

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

go30

Пример

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

gopackage main

import (
  "fmt"
  "reflect"
)

func divide(a, b float64) (float64, error) {
  if b == 0 {
    return 0, fmt.Errorf("division by zero")
  }
  return a / b, nil
}

func main() {
  fn := reflect.ValueOf(divide)
  args := []reflect.Value{
    reflect.ValueOf(10.0),
    reflect.ValueOf(2.0),
  }
  res := fn.Call(args)
  fmt.Printf("%.1f, %v\n", res[0].Float(), res[1].Interface())
}

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

go"5.0, <nil>"

Пример

Давайте вызовем функцию, которая принимает вариативный параметр:

gopackage main

import (
  "fmt"
  "reflect"
)

func sum(nums ...int) int {
  total := 0
  for _, n := range nums {
    total += n
  }
  return total
}

func main() {
  fn := reflect.ValueOf(sum)
  args := []reflect.Value{
    reflect.ValueOf([]int{1, 2, 3, 4, 5}),
  }
  res := fn.Call(args)
  fmt.Println(res[0].Int())
}

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

go15

Пример

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

gopackage main

import (
  "fmt"
  "reflect"
)

func setValue(p *int, val int) {
  *p = val
}

func main() {
  x := 10
  fn := reflect.ValueOf(setValue)
  args := []reflect.Value{
    reflect.ValueOf(&x),
    reflect.ValueOf(42),
  }
  fn.Call(args)
  fmt.Println(x)
}

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

go42

Пример

Давайте вызовем метод структуры через отражение:

gopackage main

import (
  "fmt"
  "reflect"
)

type Calculator struct {
  value int
}

func (c Calculator) Add(n int) int {
  return c.value + n
}

func main() {
  calc := Calculator{value: 10}
  method := reflect.ValueOf(calc).MethodByName("Add")
  args := []reflect.Value{
    reflect.ValueOf(5),
  }
  res := method.Call(args)
  fmt.Println(res[0].Int())
}

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

go15

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

  • метод reflect.Value.Method,
    который возвращает значение метода по индексу
  • метод reflect.Value.MethodByName,
    который возвращает значение метода по имени
  • метод reflect.Value.Interface,
    который преобразует отраженное значение в интерфейс
  • метод reflect.Value.IsValid,
    который проверяет, содержит ли значение отражения данные