zoukankan      html  css  js  c++  java
  • Golang 基础 10 -- 反射 reflection

    目录

    @

    反射基本操作

    • 反射可大大提高程序的灵活性,使得interface{}有更大的发挥余地
    • 反射使用TypeOf和ValueOf函数从 接口 中获取目标对象信息
    type User struct{
    	Id int
    	Name string
    	Age int
    }
    func (u User) Hello() {
    	fmt.Println("Hello World.")
    }
    func main(){
    	u := User{1,"kk",12}
    	Info(u)
    }
    func Info(o interface{}){
    	//获取类型信息
    	t := reflect.TypeOf(o)
    	fmt.Println("Type:",t.Name())
    
    	//用以判断传入的类型是否是struct类型,而不是指针什么的
    	if k:=t.Kind();k!=reflect.Struct {
    		fmt.Println("XXXXXXXXXX")
    		return
    	}
    	
    	//获取字段信息
    	v := reflect.ValueOf(o)
    	fmt.Println("Field:")
    
    	for i:=0;i<t.NumField();i++ {
    		f := t.Field(i)
    		val :=  v.Field(i).Interface()
    		fmt.Printf("%6s: %v = %v
    ",f.Name,f.Type,val)
    
    	//获取方法信息
    	for i:= 0;i<t.NumMethod();i++ {
    		m := t.Method(i)
    		fmt.Printf("%6s: %v
    ",m.Name,m.Type)
    	}
    }
    /*
    > Output:
    command-line-arguments
    Type: User
    Field:
        Id: int = 1
      Name: string = kk
       Age: int = 12
     Hello: func(main.User)
    */
    

    反射匿名或嵌入字段

    • 反射会将匿名字段作为独立字段(匿名字段本质)
    type User struct {
    	Id int
    	Name string
    	Age int
    }
    //匿名字段
    type Manager struct {
    	User
    	title string
    }
    func main(){
    	m := Manager{User: User{1,"hel",12}, title:"123"}
    	t := reflect.TypeOf(m)
    	//通过slice获取值
    	fmt.Printf("%#v
    ",t.FieldByIndex([]int{0,0}))
    }
    /*
    > Output:
    command-line-arguments
    reflect.StructField{Name:"Id", PkgPath:"", Type:(*reflect.rtype)(0x49ce80), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false}
    */
    

    修改目标对象

    • 想要利用反射修改对象状态,前提是interface.data是settable,即pointer-interface
    type User struct {
    	Id int
    	Name string
    	Age int
    }
    type Manager struct {
    	User
    	title string
    }
    func main(){
    	u := User{1,"ok",12}
    	Set(&u)
    	fmt.Println(u)
    }
    //通过ptr(point interface)修改字段的值
    func Set(o interface{}) {
    	v := reflect.ValueOf(o)
    	if v.Kind()!=reflect.Ptr&&!v.Elem().CanSet(){
    		fmt.Println("XXX")
    		return
    	}else{
    		v = v.Elem()
    	}
    	f:=v.FieldByName("Name")
    	if !f.IsValid(){
    		fmt.Println("BAD")
    		return
    	}
    	if f.Kind()==reflect.String {
    		f.SetString("BYBYBY")
    	}
    }
    /*
    > Output:
    command-line-arguments
    {1 BYBYBY 12}
    */
    

    动态调用方法

    • 通过反射可以“动态”调用方法
    type User struct {
    	Id int
    	Name string
    	Age int
    }
    func (u User)Hello(name string) {
    	fmt.Println("Hello",name,", my name is",u.Name)
    }
    func main() {
    	u := User{1,"OK",12}
    	v := reflect.ValueOf(u)
    	mv := v.MethodByName("Hello")
    	//args是个slice,
    	//利用反射动态调用
    	args := []reflect.Value{reflect.ValueOf("joe")}
    	mv.Call(args)
    }
    /*
    > Output:
    command-line-arguments
    Hello joe , my name is OK
    */
    
  • 相关阅读:
    MySQL数据库之WHERE条件语句
    MySQL数据库的简单操作指令之DML语言
    课程设计必备之数据库操作代码模板
    MySQL数据库之外键约束的简单理解
    pdf.js的使用
    javascript连连看
    数据库问题
    列表文字超出后,鼠标悬浮显示全部内容
    springboot component注入servecie
    点击列表 获取table tr td 下的input value
  • 原文地址:https://www.cnblogs.com/leafs99/p/golang_basic_10.html
Copyright © 2011-2022 走看看