go 反射机制

1.对单个变量

package main

import (
	"fmt"
	"reflect"
)

func test(i interface{}) {
	rty := reflect.TypeOf(i)
	fmt.Println("reflect type is", rty)
	rtv := reflect.ValueOf(i)
	fmt.Println("reflect value is", rtv)
	fmt.Printf("reflect value is%v,type is %T\n", rtv, rtv)
	iv := rtv.Interface()
	num2 := iv.(int) //断言
	fmt.Println("num2 is", num2)
}
/*
reflect type is int
reflect value is 100
reflect value is100,type is reflect.Value
num2 is 100

*/
func main() {
	var num int = 100
	test(num)
}

2.对结构体

package main

import (
	"fmt"
	"reflect"
)

type stu struct {
	age  int
	name string
}

func test(i interface{}) {
	rty := reflect.TypeOf(i)
	fmt.Println("reflect type is", rty)
	rtv := reflect.ValueOf(i)
	fmt.Println("reflect value is", rtv)

	iv := rtv.Interface()
	fmt.Printf("reflect value is%v,type is %T\n", iv, iv)
	/*
	报错:fmt.Printf("name is ", iv.name)
	反射的本质是运行时确定  编译阶段这里会报错
	因此需要先断言,修改如下:
	kv:=iv.(stu)
	fmt.Printf("name is ", kv.name)
	类型断言判断
	switch x.(type){
		case stu:
			.....
		case int
			....
		...
	}
	*/
	num2 := iv.(stu) //断言
	fmt.Println("num2 is", num2)
}

/*
reflect type is main.stu
reflect value is {6 dasf}
reflect value is{6 dasf},type is main.stu
num2 is {6 dasf}
*/
func main() {
	s := stu{name: "dasf", age: 6}
	test(s)
}

3.通过反射修改值 set方法和elem方法

package main

import (
	//"fmt"
	"reflect"
)

func test(i interface{}) {
	rval:=reflect.ValueOf(i)//rval.Kind()->ptr
	rval.SetInt(2)//报错
	/*修改:结合 ELem方法
	rval.Elem.SetInt(2)
	ptr *int=&f
	rval:=*f->修改新值
	*/
}
func main() {
	f:=10
	test(&f)//传入是指针
	
}

4.反射实践

1.使用反射遍历结构体字段和方法

package main

import (
	"fmt"
	"reflect"
)

type Monster struct {
	Name  string `json:"monster_name"`
	Age   int    `json:"monster_age"`
	Score float32
	Sex   string
}

func (s Monster) Print() {
	fmt.Println(s)
} //第一个方法
func (s Monster) Sum(i, j int) int {
	return i + j
} //第三个方法
func (s Monster) Set(name string, age int, score float32, sex string) {
	s.Name = name
	s.Age = age
	s.Score = score
	s.Sex = sex
} //第二个方法
func test(i interface{}) {
	rval := reflect.ValueOf(i)
	rty := reflect.TypeOf(i)
	kd := rval.Kind()
	if kd != reflect.Struct {
		fmt.Println("it is not struct")
		return
	}
	n := rval.NumField() //获取字段 ->4
	//遍历字段
	for j := 0; j < n; j++ {
		fmt.Println("filed", j, "is:", rval.Field(j))
		//获取标签值 使用type
		tagVal := rty.Field(j).Tag.Get("json") //json->key
		//判断该字段有没有标签
		if tagVal != "" {
			fmt.Println("filed", j, "'s tag is", tagVal)
		}

	}

	m := rval.NumMethod() //获取方法总数
	fmt.Printf("method number is %d\n", m)
	//调用方法

	rval.Method(0).Call(nil) //方法排序按照函数名字ASCII进行排序 因此调用print

	var reslice []reflect.Value //调用含参函数sum 第三个方法
	reslice = append(reslice, reflect.ValueOf(10))
	reslice = append(reslice, reflect.ValueOf(12))
	res := rval.Method(2).Call(reslice) //res->[]Value
	fmt.Printf("sum is %d\n", res[0].Int())
}
func main() {
	var a Monster = Monster{
		Name:  "哥斯拉",
		Age:   10000,
		Score: 60.6,
		Sex:   "female",
	}
	test(a)
}
/*
filed 0 is: 哥斯拉
filed 0 's tag is monster_name
filed 1 is: 10000
filed 1 's tag is monster_age
filed 2 is: 60.6
filed 3 is: female
method number is 3
{哥斯拉 10000 60.6 female}
sum is 22
*/

2.修改字段的值 结合elem()方法

package main

import (
	"fmt"
	"reflect"
)

type Monster struct {
	Name  string `json:"monster_name"`
	Age   int    `json:"monster_age"`
	Score float32
	Sex   string
}

func (s Monster) Print() {
	fmt.Println(s)
} //第一个方法
func (s Monster) Sum(i, j int) int {
	return i + j
} //第三个方法
func (s Monster) Set(name string, age int, score float32, sex string) {
	s.Name = name
	s.Age = age
	s.Score = score
	s.Sex = sex
} //第二个方法
func test(i interface{}) {
	rval := reflect.ValueOf(i)
	rty := reflect.TypeOf(i)
	kd := rval.Kind()
	if kd != reflect.Ptr && rval.Elem().Kind() == reflect.Struct {
		fmt.Println("it is not struct")
		return
	}
	n := rval.Elem().NumField() //获取字段 加入了elem方法
	//修改字段0
	方法1:
	rval.Elem().Field(0).SetString("金刚")
	方法2:
	rval.Elem().FieldByName("Name").SetString("金刚")
	
	//遍历字段
	for j := 0; j < n; j++ {
		fmt.Printf("filed %d is:%v and kind is %v\n", j, rval.Elem().Field(j), rval.Elem().Field(j).Kind())
	}
	//获取字段0标签
	tag := rty.Elem().Field(0).Tag.Get("json")
	fmt.Println(tag)
	//获取方法
	numofmethod := rval.Elem().NumMethod()
	fmt.Printf("the struct has %d methods\n", numofmethod)
	//调用第一个方法
	rval.Elem().Method(0).Call(nil)
}
func main() {
	var a Monster = Monster{
		Name:  "哥斯拉",
		Age:   10000,
		Score: 60.6,
		Sex:   "female",
	}
	test(&a) //取地址才能修改值
}
/*
filed 0 is:金刚 and kind is string
filed 1 is:10000 and kind is int
filed 2 is:60.6 and kind is float32
filed 3 is:female and kind is string
monster_name
the struct has 3 methods
{金刚 10000 60.6 female}
*/

3.测试中的适配器
文件名:01_test.go

package test

import (
	"reflect"
	"testing"
)

func TestReflect(t *testing.T) {
	call1 := func(v1 int, v2 int) {
		t.Log(v1, v2)
	}
	call2 := func(v1 int, v2 int, s string) {
		t.Log(v1, v2, s)
	}
	var (
		function reflect.Value
		inValue  []reflect.Value
		n        int
	)

	//适配器
	bridge := func(call interface{}, args ...interface{}) {
		n = len(args)
		inValue = make([]reflect.Value, n)
		for i := 0; i < n; i++ {
			inValue[i] = reflect.ValueOf(args[i])
		}
		function = reflect.ValueOf(call)
		function.Call(inValue)
	}
	bridge(call1, 1, 2)
	bridge(call2, 1, 2, "test2")
}

//命令行输入
C:\Users\rubylee\go\src\sad>go test -v 01_test.go
//输出
=== RUN   TestReflect
    01_test.go:10: 1 2
    01_test.go:13: 1 2 test2
--- PASS: TestReflect (0.00s)
PASS
ok      command-line-arguments  0.584s

4.使用反射操作任意结构体

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值