• Home
  • About
    • Shadow Knight photo

      Shadow Knight

      https://live.bilibili.com/9565678

    • Learn More
    • Twitter
    • Facebook
    • Instagram
    • Github
    • Steam
  • Posts
    • All Posts
    • All Tags
  • Projects

golang反射

31 May 2018

Reading time ~1 minute

golang反射

反射类型与反射值

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string
	Age  int
	Sex  string
}

func (p Person) Say(msg string) {
	fmt.Println("hello,", msg)
}
func (p Person) PrintInfo() {
	fmt.Printf("姓名:%s,年龄:%d,性别:%s\n", p.Name, p.Age, p.Sex)
}

func main() {
	//1.创建一个struct的对象
	p1 := Person{"王二狗", 30, "男"}
	//1.第一部分:通过反射操作结构体中的字段:获取字段的类型,名称,数值。。
	//通过reflect包下的TypeOf(),获取p1的类型

	//反射值&&方法的类型和名字
	t1 := reflect.TypeOf(p1)
	fmt.Println(t1)        //main.Person
	fmt.Println(t1.Name()) //Person
	fmt.Println(t1.Kind()) //struct
	//通过reflect包下ValueOf(),获取p1的值
	v1 := reflect.ValueOf(p1) //{王二狗 30 男}=fmt.Println(p1)
	fmt.Println(v1)
	fmt.Println(p1)

	//详细操作:判断t1的种类是结构体类型
	//判断是否为结构体
	if t1.Kind() == reflect.Struct {
		//获取字段的数量
		count := t1.NumField() //3个字段
		fmt.Println(count)

		for i := 0; i < count; i++ {
			filed := t1.Field(i)
			val := v1.Field(i).Interface() //根据v1获取对应字段的数值,--->空接口类型
			//fmt.Println(filed)
			fmt.Println("字段名称:", filed.Name, "字段类型:", filed.Type, "字段数值:", val)
		}
	}
	//2.通过反射,操作方法
	fmt.Println(t1.NumMethod())
	for i := 0; i < t1.NumMethod(); i++ {
		method := t1.Method(i)
               //方法名和类型
//PrintInfo func(main.Person)
//Say func(main.Person, string)

		fmt.Println(method.Name, method.Type)
	}
	//执行方法
	m1 := v1.MethodByName("PrintInfo")
	m1.Call(nil) //执行m1对应的PrintInfo()

	m2 := v1.MethodByName("Say")
	m2.Call([]reflect.Value{reflect.ValueOf("你好啊")}) // string-->Value

}

通过下标去反射匿名函数

package main

import (
	"fmt"
	"reflect"
)

type Animal struct {
	Name string
	Age  int
}

type Cat struct {
	Animal
	Color string
}

func main() {
	c1 := Cat{Animal{"猫咪", 1}, "白色"}

	t1 := reflect.TypeOf(c1)
	fmt.Println(t1.NumField())

	//循环输出结构体的字段名称与类型
	for i := 0; i < t1.NumField(); i++ {
		field := t1.Field(i)
		fmt.Println(field)
	}

	//获取匿名字段
	/*
		匿名字段,可以通过下标获取
		FieldByIndex([]int{0})-->Animal
		FieldByIndex([]int{0,0})-->Animal中的第一个字段:Name
	*/
	f1 := t1.FieldByIndex([]int{0, 0})
	fmt.Println(f1.Name, f1.Type) //Name string
	f2 := t1.FieldByIndex([]int{0, 1})
	fmt.Println(f2.Name, f2.Type)

	v1 := reflect.ValueOf(c1)

	name := v1.FieldByIndex([]int{0, 0})
	age := v1.FieldByIndex([]int{0, 1})
	fmt.Println(name) //猫咪
	fmt.Println(age)  //1

}

通过反射修改数值

package main

import (
	"reflect"
	"fmt"
)

type Student struct {
	Name string
	Age int
	School string
}
func main()  {
	/*
	通过反射,来更改对象的数值:前提是数据可以被更改
	 */
	 s1:=Student{"王二狗",19,"新东方"}
	 fmt.Printf("%T\n",s1) //main.Student
	 p1:=&s1
	 fmt.Printf("%T\n",p1) //*main.Student
	 fmt.Println(s1.Name)
	 fmt.Println((*p1).Name,p1.Name)
         
         //传指针才能改数值
	 v1:= reflect.ValueOf(&s1) // value

	 if v1.Kind()==reflect.Ptr{
	 	fmt.Println(v1.Elem().CanSet())
	 	v1 = v1.Elem()
	 }
         //通过找到字段名称修改值变量
	 f1:=v1.FieldByName("Name")
	 f1.SetString("王三狗")
	 f3:=v1.FieldByName("School")
	 f3.SetString("蓝翔学校")
	 fmt.Println(s1)
}



golang反射 Share Tweet +1