定义:

ValueOf用来获取输入参数接口中的数据的值,如果接口为空则返回0

TypeOf用来动态获取输入参数接口中的值的类型,如果接口为空则返回nil

package main

import (
	"fmt"
	"reflect"
)

func main() {
	// 反射操作:通过反射,可以获取一个接口类型变量的 类型和数值
	var x float64 = 3.4

	fmt.Println("type: ", reflect.TypeOf(x))   // type:  float64
	fmt.Println("value: ", reflect.ValueOf(x)) // value:  3.4

	// 根据反射的值,获取对应的类型和值
	v := reflect.ValueOf(x)
	fmt.Println("kind is float64: ", v.Kind() == reflect.Float64) // kind is float64:  true
	fmt.Println("type:", v.Type())                                // type: float64
	fmt.Println("value:", v.Float())                              // value: 3.4
}

go类型定义:

  • 静态类型

静态类型在编译时都是确定的,例如:int,float32,*int,[]byte,chan []int

// 静态类型
type Myint int

var i *int
  • 动态类型

运行时给这个变量赋值,这个变量的动态类型,取决与它的赋值类型。前提是这个变量是一个接口类型

// 动态类型
var a interface{}  // 静态类型为interface{}

a = 10  // 动态类型为int
a = "abc"  // 动态类型为string

类型转换:

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var x float64 = 3.4

	// 接口类型变量 -> 反射类型对象
	value := reflect.ValueOf(x)
	fmt.Printf("value:%v, type:%T\n", value, value) // value:3.4, type:reflect.Value

	// 反射类型对象 -> 接口类型变量,理解为’强制转换‘
	convertValue := value.Interface().(float64)
	fmt.Printf("value:%v, type:%T\n", convertValue, convertValue) // value:3.4, type:float64

	pointer := reflect.ValueOf(&x)
	convertPointer := pointer.Interface().(*float64)
	fmt.Printf("value:%v, type:%T", convertPointer, convertPointer)  // value:0xc000014088, type:*float64

}

结构体使用reflect:

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string
	Age  int
}

func (p Person) Say(msg string) {
	fmt.Println("hello ", msg)
}

func (p Person) PrintInfo() {
	fmt.Printf("姓名:%s, 年龄:%d\n", , p.Age)
}

func GetMessage(inp interface{}) {
	getType := reflect.TypeOf(inp)               // 先获取inp的类型
	fmt.Println("get type is: ", ()) // get type is:  Person
	fmt.Println("get kind is: ", getType.Kind()) // get kind is:  struct

	getValue := reflect.ValueOf(inp)
	fmt.Println("get all Fields is: ", getValue) // get all Fields is:  {zhangsa 11}

	// 获取每个字段信息
	/*
		1.先获取Type对象:reflect.Type
			NumField()
			Field(index)
		2.通过Field()获取每一个Field字段
		3.interface()获取对应value
	*/
	for i := 0; i < getType.NumField(); i++ {
		field := getType.Field(i)
		value := getValue.Field(i).Interface()

		fmt.Printf("字段名称:%s, 字段类型:%s, 字段数值:%v\n", , field.Type, value)
		// 字段名称:Name, 字段类型:string, 字段数值:zhangsa
		// 字段名称:Age, 字段类型:int, 字段数值:11
	}
	// 直接通过FieldByName获取某个字段名称
	name := getValue.FieldByName("Name")
	fmt.Println("name: ", name)  // name:  zhangsa

	// 获取方法
	for i := 0; i < getType.NumMethod(); i++ {
		method := getType.Method(i)
		fmt.Printf("方法名称:%s, 方法类型:%v\n", method.Name, method.Type)
		// 方法名称:PrintInfo, 方法类型:func(main.Person)
		// 方法名称:Say, 方法类型:func(main.Person, string)
	}
}

func main() {
	p := Person{Name: "zhangsa", Age: 11}
	GetMessage(p)
}

通过reflect.Value设置实际变量的值:

reflect.Value是通过reflect.ValueOf(x)获得的,只有当x是指针的时候,才可以通过reflect.Value修改实际变量x的值

即:通过refPtrVal := reflect.ValueOf(&var)的方式获取指针类型,然后使用refPtrVal.elem().set(一个新的reflect.Value)来进行更改

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var n float64 = 2.3
	fmt.Println("n: ", n) // 2.3

	// 获取&n的reflect值对象
	pointer := reflect.ValueOf(&n) // 需要操作指针
	// 获取原始值(n)对应的反射对象
	newValue := pointer.Elem()

	fmt.Println("类型:", newValue.Type())         // float64
	fmt.Println("是否可以修改数据:", newValue.CanSet()) // true

	// 重新赋值
	newValue.SetFloat(3.5)
	fmt.Println(n) // 3.5

}
package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	p := Person{"zsan", 11}
	fmt.Printf("%T\n", p) // main.Person
	p2 := &p
	fmt.Printf("%T\n", p2) // *main.Person

	fmt.Println() // zsan

	// 简写
	fmt.Println()    // zsan
	fmt.Println((*p2).Name) // zsan

	// 改变数值
	value := reflect.ValueOf(&p)
	typ := reflect.TypeOf(&p)
	fmt.Printf("%v\n", typ.Kind())   // ptr
	fmt.Printf("%v\n", value.Kind()) // ptr

	if value.Kind() == reflect.Ptr {
		newValue := value.Elem()
		fmt.Println(newValue.CanSet()) // true

		name := newValue.FieldByName("Name")
		fmt.Println("name: ", name) // name:  zsan
		name.SetString("lisi444")
		fmt.Println(p) // {lisi444 11}

	}

}

方法的调用:

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string
	Age  int
}

func (p Person) Say(msg string) {
	fmt.Println("hello ", msg)
}

func (p Person) PrintInfo() {
	fmt.Printf("姓名:%s, 年龄:%d\n", , p.Age)
}

func (p Person) Test(i, j int, m string) {
	fmt.Printf("%d%d%s", i, j, m)
}

func main() {
	/*
	   通过反射进行方法的调用
	   1.接口变量->反射对象(value)
	   2.获取对应的方法对象:MethodByName()
	   3.将方法对象进行调用:Call()
	*/
	p := Person{"zhangsan", 22}
	value := reflect.ValueOf(p)
	fmt.Printf("kind: %s, type: %s\n", value.Kind(), value.Type()) // kind: struct, type: main.Person

	// 调用无参数方法
	methodValue1 := value.MethodByName("PrintInfo")
	fmt.Printf("kind: %s, type: %s\n", methodValue1.Kind(), methodValue1.Type()) // kind: func, type: func()
	// 没有参数时,直接调用,
	// 方式1 没有参数,直接写nil
	methodValue1.Call(nil) // 姓名:zhangsan, 年龄:22
	// 方式2 创建一个空的切片
	args1 := make([]reflect.Value, 0)
	methodValue1.Call(args1) // 姓名:zhangsan, 年龄:22

	// 调用1个参数方法
	methodValue2 := value.MethodByName("Say")
	fmt.Printf("kind: %s, type: %s\n", methodValue2.Kind(), methodValue2.Type()) // kind: func, type: func(string)
	args2 := []reflect.Value{reflect.ValueOf("反射机制传参")}
	methodValue2.Call(args2) /// hello  反射机制传参

	// 调用多个参数方法
	methodValue3 := value.MethodByName("Test")
	fmt.Printf("kind: %s, type: %s\n", methodValue3.Kind(), methodValue3.Type()) // kind: func, type: func(int, int, string)
	args3 := []reflect.Value{reflect.ValueOf(1), reflect.ValueOf(2), reflect.ValueOf("反射机制传参")}
	methodValue3.Call(args3) // 12反射机制传参

}

函数的调用:

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

func fun1() {
	fmt.Println("我是函数fun1(), 无参数。。")
}

func fun2(i int, s string) {
	fmt.Println("我是函数fun2(), 有参数。。")
}

func fun3(i int, s string) string {
	fmt.Println("我是函数fun3(), 无参数,也有返回值")
	return s + strconv.Itoa(i)
}

func main() {
	// 函数的反射
	/*
		1.函数->反射对象
		2.kind->func
		3.call()
	*/
	f1 := fun1
	value := reflect.ValueOf(f1)
	fmt.Printf("kind: %s, type: %s\n", value.Kind(), value.Type()) // kind: func, type: func()

	value2 := reflect.ValueOf(fun2)
	fmt.Printf("kind: %s, type: %s\n", value2.Kind(), value2.Type()) // kind: func, type: func(int, string)
	value3 := reflect.ValueOf(fun3)
	fmt.Printf("kind: %s, type: %s\n", value3.Kind(), value3.Type()) // kind: func, type: func(int, string) string

	// 通过反射调用函数
	value.Call(nil)
	value2.Call([]reflect.Value{reflect.ValueOf(22), reflect.ValueOf("hello")})
	result := value3.Call([]reflect.Value{reflect.ValueOf(33), reflect.ValueOf("nihao")})
	fmt.Printf("%T\n", result)                                             // []reflect.Value
	fmt.Println(len(result))                                               // 1
	fmt.Printf("kind: %s, type: %s\n", result[0].Kind(), result[0].Type()) // kind: string, type: string

	s := result[0].Interface().(string)
	fmt.Println(s)        // nihao33
	fmt.Printf("%T\n", s) // string

}