Go语言中的反射是指在程序运行时检查程序的结构,比如变量的类型、方法的签名等。Go语言的反射包是reflect。通过反射,你可以动态地检查类型信息、获取字段和方法、调用方法等。
反射可以在运行时动态获取变量的各种信息,比如变量的类型、值等
如果是结构体,还可以获取到结构体本身的各种信息,比如结构体的字段、方法
通过反射,还可以修改变量的值、调用方法
使用反射,需要引入一个包:reflect,它定义了内个重要的类型 Type 和 Value 任意接口值在反射中都可以理解为由 reflect.Type 和 reflect.Value两部分组成,并且reflect 包提供了 reflect.Typ!alue和Type.Of和 reflect.ValueOf 两个函数来获取任意对象的 V
(Type)和种类(Kind)的区别。编程中,使用最多的是类型,但在反射中,当需要区分一个品种的类型时在使用反射时,需要首先理解类型.就会用到种类(Kind)。
package main
import (
"fmt"
"reflect"
)
func main() {
var a float64 = 3.14
fmt.Println(reflect.TypeOf(a))
fmt.Println(reflect.ValueOf(a))
v := reflect.ValueOf(a)
if v.Kind() == reflect.Float64 {
fmt.Println("v.kind() is float64")
}
fmt.Println(v.Type())
fmt.Println(v.Float())
}
需要反射的2个常见场景:
但是对于反射,还是有几点不太建议使用反射的理由:
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Age int
Sex string
}
func (user User) Say(msg string) {
fmt.Println("user说", msg)
}
func main() {
user := User{Name: "xiaolong", Age: 18, Sex: "男"}
reflectGetInfo(user)
}
func reflectGetInfo(input interface{}) {
//获取参数类型
getType := reflect.TypeOf(input)
fmt.Println("type is", getType.Name())
fmt.Println("kind is", getType.Kind())
//获取值
getValue := reflect.ValueOf(input)
fmt.Println("getValue is", getValue)
//通过反射获取反射结果内的字段与方法
for i := 0; i < getType.NumField(); i++ {
filed := getType.Field(i)
value := getValue.Field(i).Interface()
fmt.Println(filed.Name, filed.Type, value)
}
for i := 0; i < getType.NumMethod(); i++ {
method := getType.Method(i)
fmt.Println(method.Name, method.Type)
}
}
package main
import (
"fmt"
"reflect"
)
func main() {
var num float64 = 1.23
point := reflect.ValueOf(&num) //想要通过指针修改值,需要传入指针
newValue := point.Elem()
fmt.Println(newValue.Kind())
fmt.Println(newValue.Type())
fmt.Println(newValue.CanSet())
if newValue.CanSet() {
newValue.SetFloat(3.14)
}
fmt.Println(num)
}
修改结构体
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Age int
Sex string
}
func (user User) Say(msg string) {
fmt.Println("user说", msg)
}
func main() {
user := User{Name: "xiaolong", Age: 18, Sex: "男"}
fmt.Println(user)
newValue := reflect.ValueOf(&user)
if newValue.Kind() == reflect.Ptr { //首先是指针
valueTemp := newValue.Elem()
if valueTemp.CanSet() {
valueTemp.FieldByName("Name").SetString("dalong")
valueTemp.FieldByName("Age").SetInt(38)
}
}
fmt.Println(user)
}
方法调用
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Age int
Sex string
}
func (user User) Say(msg string) {
fmt.Println("user说", msg)
}
func (user User) GetInfo() {
fmt.Println("user 信息", user.Name, user.Age)
}
func main() {
user := User{Name: "xiaolong", Age: 18, Sex: "男"}
//reflectGetInfo(user)
fmt.Println(user)
//无参数方法调用
value := reflect.ValueOf(user)
value.MethodByName("GetInfo").Call(nil)
//有参数方法调用
args := make([]reflect.Value, 1)
args[0] = reflect.ValueOf("反射调用")
value.MethodByName("Say").Call(args)
}
函数调用
package main
import (
"fmt"
"reflect"
)
func main() {
v1 := reflect.ValueOf(func1)
v1.Call(nil)
v2 := reflect.ValueOf(func2)
args := make([]reflect.Value, 2)
args[0] = reflect.ValueOf(1)
args[1] = reflect.ValueOf("gagaga")
v2.Call(args)
v3 := reflect.ValueOf(func3)
args1 := make([]reflect.Value, 2)
args1[0] = reflect.ValueOf(1)
args1[1] = reflect.ValueOf("gagaga")
res := v3.Call(args1)
fmt.Println(res[0].Interface())
}
func func1() {
fmt.Println("无参数fun1")
}
func func2(i int, s string) {
fmt.Println("有参数fun2", i, s)
}
func func3(i int, s string) string {
fmt.Println("有参数fun3", i, s)
return s
}