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.使用反射操作任意结构体