Тип reflect.Type
Тип reflect.Type представляет собой интерфейс,
который содержит информацию о типе данных во время
выполнения программы. Он позволяет получать различные
сведения о типе: его имя, пакет, размер, структуру полей
и методов. Основным способом получения значения
reflect.Type является вызов функции
reflect.TypeOf, которая возвращает тип переданного
значения. Этот интерфейс предоставляет множество методов
для анализа и работы с типами данных в рефлексии.
Получение типа значения
Для получения типа переменной используется функция
reflect.TypeOf, которая возвращает значение
интерфейса reflect.Type. Если передать nil,
функция вернет nil.
package main
import (
"fmt"
"reflect"
)
func main() {
var num int = 42
var str string = "hello"
var arr [3]int
typeOfNum := reflect.TypeOf(num)
typeOfStr := reflect.TypeOf(str)
typeOfArr := reflect.TypeOf(arr)
fmt.Println(typeOfNum)
fmt.Println(typeOfStr)
fmt.Println(typeOfArr)
}
Результат выполнения кода:
"int"
"string"
"[3]int"
Получение имени и пути пакета
Методы Name и PkgPath позволяют получить
имя типа и путь пакета, в котором он объявлен. Для
встроенных типов имя возвращается, а путь пакета будет
пустой строкой.
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Age int
}
func main() {
var u User
t := reflect.TypeOf(u)
fmt.Println(t.Name())
fmt.Println(t.PkgPath())
var num int
tInt := reflect.TypeOf(num)
fmt.Println(tInt.Name())
fmt.Println(tInt.PkgPath())
}
Результат выполнения кода:
"User"
"main"
"int"
""
Получение строкового представления
Метод String возвращает строковое представление
типа, которое может использоваться для вывода или
сравнения. Это представление соответствует синтаксису
объявления типа в Go.
package main
import (
"fmt"
"reflect"
)
func main() {
var slice []int
var m map[string]int
var fn func(int) string
fmt.Println(reflect.TypeOf(slice).String())
fmt.Println(reflect.TypeOf(m).String())
fmt.Println(reflect.TypeOf(fn).String())
}
Результат выполнения кода:
"[]int"
"map[string]int"
"func(int) string"
Проверка реализации интерфейса
Метод Implements позволяет проверить,
реализует ли тип заданный интерфейс. Для этого необходимо
передать reflect.Type интерфейса, который нужно
проверить.
package main
import (
"fmt"
"reflect"
)
type Stringer interface {
String() string
}
type MyInt int
func (m MyInt) String() string {
return fmt.Sprintf("%d", m)
}
func main() {
var i MyInt
t := reflect.TypeOf(i)
interfaceType := reflect.TypeOf((*Stringer)(nil)).Elem()
fmt.Println(t.Implements(interfaceType))
var num int
tInt := reflect.TypeOf(num)
fmt.Println(tInt.Implements(interfaceType))
}
Результат выполнения кода:
"true"
"false"
Получение информации о структуре
Методы NumField и Field позволяют получить
информацию о полях структуры. Метод NumField
возвращает количество полей, а Field по индексу
возвращает объект reflect.StructField с
информацией о поле.
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string
Age int
Address string
}
func main() {
p := Person{"John", 30, "123 Main St"}
t := reflect.TypeOf(p)
fmt.Println(t.NumField())
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fmt.Printf("%s: %s\n", field.Name, field.Type)
}
}
Результат выполнения кода:
"3"
"Name: string"
"Age: int"
"Address: string"
Получение информации о методах
Методы NumMethod и Method позволяют
получить информацию о методах типа. Метод NumMethod
возвращает количество методов, а Method по индексу
возвращает объект reflect.Method с информацией о
методе.
package main
import (
"fmt"
"reflect"
)
type Calculator struct{}
func (c Calculator) Add(a, b int) int {
return a + b
}
func (c Calculator) Sub(a, b int) int {
return a - b
}
func main() {
var calc Calculator
t := reflect.TypeOf(calc)
fmt.Println(t.NumMethod())
for i := 0; i < t.NumMethod(); i++ {
method := t.Method(i)
fmt.Printf("%s: %v\n", method.Name, method.Type)
}
}
Результат выполнения кода:
"2"
"Add: func(main.Calculator, int, int) int"
"Sub: func(main.Calculator, int, int) int"
Получение элемента составного типа
Метод Elem возвращает тип элемента для составных
типов: указателей, массивов, срезов, каналов и карт. Это
позволяет получить информацию о типе, на который указывает
указатель, или о типе элементов среза.
package main
import (
"fmt"
"reflect"
)
func main() {
var ptr *int
var slice []string
var arr [5]bool
tPtr := reflect.TypeOf(ptr)
tSlice := reflect.TypeOf(slice)
tArr := reflect.TypeOf(arr)
fmt.Println(tPtr.Elem())
fmt.Println(tSlice.Elem())
fmt.Println(tArr.Elem())
}
Результат выполнения кода:
"int"
"string"
"bool"
Проверка совместимости типов
Метод AssignableTo проверяет, можно ли присвоить
значение одного типа переменной другого типа. Метод
ConvertibleTo проверяет, можно ли преобразовать
значение одного типа к другому.
package main
import (
"fmt"
"reflect"
)
type MyInt int
func main() {
var i int
var mi MyInt
var f float64
tInt := reflect.TypeOf(i)
tMyInt := reflect.TypeOf(mi)
tFloat := reflect.TypeOf(f)
fmt.Println(tInt.AssignableTo(tMyInt))
fmt.Println(tInt.ConvertibleTo(tMyInt))
fmt.Println(tInt.ConvertibleTo(tFloat))
}
Результат выполнения кода:
"false"
"true"
"true"
Смотрите также
-
функцию
reflect.TypeOf,
которая возвращает тип значения -
тип
reflect.Value,
который представляет значение во время выполнения -
метод
reflect.Type.Kind,
который возвращает базовый вид типа -
структуру
reflect.StructField,
которая содержит информацию о поле структуры