复制到自己的编辑器, 从main函数看
package main
import (
"fmt"
"reflect"
)
func reflectTest01(b interface{}) {
//通过反射获取的传入的变量的 type , kind, 值
//1. 先获取到 reflect.Type
rtype := reflect.TypeOf(b)
fmt.Println(rtype)
//2. 获取到 reflect.Value
rval := reflect.ValueOf(b)
n2 := 2 + rval.Int()
fmt.Println("n2=", n2)
//下面我们将 rVal 转成 interface{}
iv := rval.Interface()
//将 interface{} 通过断言转成需要的类型
num2 := iv.(int)
fmt.Println("num2=", num2)
}
type Student struct {
Name string
Age int
}
func reflectTest02(b interface{}) {
//通过反射获取的传入的变量的 type , kind, 值
//1. 先获取到 reflect.Type
rtype := reflect.TypeOf(b)
fmt.Println(rtype)
//2. 获取到 reflect.Value
rval := reflect.ValueOf(b)
// 将 rVal 转成 interface{}
iv := rval.Interface()
fmt.Printf("iv=%v iv type=%T
", iv, iv)
// 使用类型推断将interface转换为需要的类型
stu, ok := iv.(Student)
if ok {
fmt.Printf("stu.name=%v
", stu.Name)
}
}
func reflectTest03(b interface{}) {
v1 := reflect.ValueOf(b)
fmt.Printf("val type=%T
", v1)
v1.Elem().SetInt(100) // 通过反射设置值
fmt.Printf("val=%v
", v1)
}
func reflectTest04(b interface{}) {
rtype := reflect.TypeOf(b) // main.Student
val := reflect.ValueOf(b) // { 0}
fmt.Printf("%v
", rtype)
fmt.Printf("%v
", val)
fmt.Printf("%v
", val.Kind()) // struct
v2 := val.Interface()
fmt.Printf("%v
", v2) // 将reflect.Value -> interface{}
v3, ok := v2.(float64) // 将interface{} -> float64
if ok {
fmt.Println(v3)
fmt.Printf("%v, %T", v3, v3)
}
}
type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
Score float64 `json:"score"`
Sex string
}
func (this Monster) GetSum(n1, n2 int) int {
return n1 + n2
}
func (this Monster) Set(name string, age int, score float64, sex string) {
this.Name = name
this.Age = age
this.Score = score
this.Sex = sex
}
func (this Monster) Print() {
println("------start---------")
fmt.Println(this)
println("------end---------")
}
func reflectTest05(a interface{}) {
typ := reflect.TypeOf(a) // 获取类型
val := reflect.ValueOf(a) // 获取值
kd := val.Kind() // 获取kind
fmt.Println(kd, "---------------------------")
if kd != reflect.Struct {
fmt.Println("expect struct, actul is: ", kd)
return
}
num := val.NumField() // 获取字段数目
fmt.Printf("struct has %d files
", num)
// 遍历字段
for i := 0; i < num; i++ {
fmt.Printf("Filed %d: 值为=%v
", i, val.Field(i))
// 获取struct标签, 通过reflect.Type 来获取tag标签的值
tagVal := typ.Field(i).Tag.Get("json")
// 如果该字段于tag标签的显示, 否则就不显示
if tagVal != "" {
fmt.Printf("filed %d, tag为=%v
", i, tagVal)
}
}
// 获取结构的多少方法
numOfMethod := val.NumMethod()
fmt.Printf("struct had %d methods
", numOfMethod)
//var params []reflect.Value
//方法的排序默认是按照 函数名的排序(ASCII 码)
val.Method(1).Call(nil) // 获取第二个方法, 调用它
// 调用结构体的第一个方法 Method(0)
var params []reflect.Value
params = append(params, reflect.ValueOf(10))
params = append(params, reflect.ValueOf(40))
// 传入的参数是[]reflect.Value, 返回reflect.value
res := val.Method(0).Call(params)
fmt.Println("res=", res) // []reflect.value */
}
func reflectTest06(a interface{}) {
typ := reflect.TypeOf(a) // 获取类型
val := reflect.ValueOf(a) // 获取值
kd := val.Kind() // 获取kind
fmt.Println(kd, "---------------------------")
if kd != reflect.Struct {
fmt.Println("expect struct, actul is: ", kd)
return
}
num := typ.NumField() // 获取字段数目
fmt.Printf("struct has %d files
", num)
// 遍历字段
for i := 0; i < num; i++ {
filed := typ.Field(i)
value := val.Field(i).Interface()
fmt.Printf("%s: %v = %v
", filed.Name, filed.Type, value)
}
// 获取结构的多少方法
for i := 0; i < typ.NumMethod(); i++ {
m := typ.Method(i)
fmt.Printf("%s : %v
", m.Name, m.Type)
}
}
func test1() {
slice := []int{1, 2, 3, 4, 5}
m := make(map[int]int)
for key, val := range slice {
fmt.Println(key, val, &val)
m[key] = val
}
for key := range m {
// 都是5, 为什么?
// 可以理解为上面的val始终使用的是同一个地址, 值一致在被修改而地址不变(面试题)
fmt.Println(m[key])
}
}
func main() {
// var num int = 100
// reflectTest01(num) // (基本数据类型、interface{}、reflect.Value)进行反射的基本操作
// stu := Student{
// Name: "tom",
// Age: 12,
// }
// reflectTest02(stu) // (基本数据类型、interface{}、reflect.Value)进行反射的基本操作
// var a = 10
// reflectTest03(&a) // 通过反射修改值, 需要传入指针
// fmt.Println(a)
/*
reflect.Value.Elem() var num = 10; var b *int = # *b = 100
*/
// var f1 = 10.2
// // var f1 = Student{}
// reflectTest04(f1) // 练习 给你一个变量 var v float64 = 1.2 , 请使用反射来得到它的 reflect.Value, 然后获取对应Type,Kind 和值,并将 reflect.Value 转换成 interface{} , 再将 interface{} 转换成 float64.
// var m1 = Monster{
// Name: "牛魔王",
// Age: 12,
// Score: 12.2,
// Sex: "femal",
// }
// reflectTest05(m1) //通过获取方法, 字段等 m1的方法绑定时需要和Monster, 而不是*Monster, 要不然获取不出来方法
// https://studygolang.com/articles/12348?fr=sidebar 具体仔细阅读这个博客
// reflectTest06(m1) // 获取字段类型以及方法类型
test1() // 面试题
}
/*
1) reflect.Value.Kind,获取变量的类别,返回的是一个常量
2) Type 和 Kind 的区别
Type 是类型, Kind 是类别, Type 和 Kind 可能是相同的,也可能是不同的.
比如: var num int = 10 num 的 Type 是 int , Kind 也是 int
比如: var stu Student stu 的 Type 是 pkg1.Student , Kind 是 struct
3) 通过 反射可以将变量在interface{}和Reflet.Value之间转换
变量<---------> interface{} <------------> reflect.Value
4)式用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配,比如x是int,
那么就应该使用reflect.Value(x).Int(),而不能使用其它的,否则报panic
5) 通过反射的来修改变量, 注意当使用 SetXxx 方法来设置需要通过对应的指针类型来完成, 这样
才能改变传入的变量的值, 同时需要使用到 reflect.Value.Elem()方
*/