Тип reflect.Value

Тип reflect.Value представляет собой динамическое значение, полученное через отражение (reflection). Он предоставляет методы для чтения и изменения значений любого типа во время выполнения. Основной способ получения reflect.Value - функция reflect.ValueOf, которая принимает интерфейс и возвращает его отраженное представление. Тип reflect.Value позволяет получить информацию о значении, его типе, а также изменять его, если оно доступно для установки.

Создание reflect.Value

Рассмотрим базовый пример получения reflect.Value с помощью функции reflect.ValueOf:

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  x := 42
  val := reflect.ValueOf(x)
  fmt.Println(val)
}

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

go"42"

Получение значения через Interface

Метод Interface преобразует reflect.Value обратно в interface{}, позволяя работать с исходным значением:

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  x := 3.14
  val := reflect.ValueOf(x)
  interf := val.Interface()
  res := interf.(float64) + 1.0
  fmt.Println(res)
}

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

go"4.14"

Проверка валидности значения

Метод IsValid проверяет, представляет ли reflect.Value действительное значение (не нулевое):

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  var x interface{}
  val := reflect.ValueOf(x)
  res := val.IsValid()
  fmt.Println(res)
}

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

go"false"

Проверка на nil

Метод IsNil проверяет, является ли значение nil для указателей, интерфейсов, мапов, слайсов, каналов и функций:

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  var ptr *int
  val := reflect.ValueOf(ptr)
  res := val.IsNil()
  fmt.Println(res)
}

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

go"true"

Проверка на нулевое значение

Метод IsZero проверяет, является ли значение нулевым для своего типа:

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  var s string
  val := reflect.ValueOf(s)
  res := val.IsZero()
  fmt.Println(res)
}

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

go"true"

Получение типа значения

Метод Type возвращает reflect.Type, представляющий тип значения:

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  x := "hello"
  val := reflect.ValueOf(x)
  t := val.Type()
  fmt.Println(t)
}

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

go"string"

Получение вида значения (Kind)

Метод Kind возвращает вид значения (константу reflect.Kind):

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  x := 100
  val := reflect.ValueOf(x)
  k := val.Kind()
  fmt.Println(k)
}

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

go"int"

Изменение значения через Set

Для изменения значения необходимо использовать метод Set, но только если значение доступно для установки (проверяется через CanSet):

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  x := 10
  val := reflect.ValueOf(&x).Elem()
  if val.CanSet() {
    val.SetInt(20)
  }
  fmt.Println(x)
}

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

go"20"

Работа с указателями

Метод Elem возвращает значение, на которое указывает указатель или интерфейс:

gopackage main

import (
  "fmt"
  "reflect"
)

func main() {
  x := 100
  ptr := &x
  val := reflect.ValueOf(ptr).Elem()
  fmt.Println(val)
}

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

go"100"

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

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