zoukankan      html  css  js  c++  java
  • Golang 反射

    反射是指程序运行期间对程序本身进行访问和修改的能力

    变量的内在机制

    • 变量包含类型信息和值信息
    • 类型信息:是静态的元信息,是预先定义好的
    • 值信息:是程序运行过程中动态改变的

    反射的使用

    • reflect 包封装了反射相关的方法
    • 获取类型信息:reflect.TypeOf,是静态的
    • 获取值信息:reflect.ValueOf,是动态的

    空接口与反射

    • 反射可以在运行时动态获取程序的各种详细信息
    • 反射获取 interface 类型信息
    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 反射获取interface类型
    func relect_type(i interface{}) {
    	// typeOf不能直接比较
    	t := reflect.TypeOf(i)
    	fmt.Println("类型是: ", t)
    
    	// kind() 可以获取具体类型
    	k := t.Kind()
    	fmt.Println(k)
    
    	switch k {
    	case reflect.Float64:
    		fmt.Println("i is float64")
    	case reflect.String:
    		fmt.Println("i is string")
    	}
    }
    
    func main() {
    	var x float64 = 2.4
    	relect_type(x)
    }
    

    反射获取 interface 值信息

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 反射获取interface值信息
    func relect_value(i interface{}) {
    	v := reflect.ValueOf(i)
    	fmt.Println(v)
    	k := v.Kind()
    	switch k {
    	case reflect.Float64:
    		fmt.Println("a is: ", v.Float())
    	}
    }
    
    func main() {
    	var x float64 = 3.14
    	relect_value(x)
    }
    

    反射修改值信息

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 反射修改值信息
    func reflect_set_value(i interface{}) {
    	v := reflect.ValueOf(i)
    	k := v.Kind()
    	switch k {
    	case reflect.Float64:
    		// 值传递无法在反射中修改
    		// 反射修改值
    		v.SetFloat(99.81)
    		fmt.Println("value is, ", v.Float())
    	case reflect.Ptr:
    		// Elem()获取地址中的值
    		v.Elem().SetFloat(88.91)
    		fmt.Println("ptr value is, ", v.Elem().Float())
    		// 地址
    		fmt.Println(v.Pointer())
    	}
    }
    
    func main() {
    	var x float64 = 3.14
    	// 反射值类型, 值传递无法在反射中修改
    	//reflect_set_value(x)
    	//fmt.Println("main value, ", x)
    	// 反射一个指针类型
    	reflect_set_value(&x)
    	fmt.Println("ptr main value, ", x)
    }
    

    结构体反射

    查看类型、字段和方法

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 定义结构体
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    // 绑定方法
    func (u User) Hello() {
    	fmt.Println("hello")
    }
    
    func reflect_struct(i interface{}) {
    	t := reflect.TypeOf(i)
    	fmt.Println("类型: ", t)
    	fmt.Println("字符串类型: ", t.Name())
    
    	// 获取值
    	v := reflect.ValueOf(i)
    	fmt.Println("值: ", v)
    	// 获取结构体所有属性
    	// 获取结构体字段个数: t.NumField()
    	for i := 0; i < t.NumField(); i++ {
    		// 取每个字段
    		// 通过interface{} 的 TypeOf()获取
    		f := t.Field(i)
    		// f.Name 字段名称  f.Type  字段类型
    		fmt.Printf("%s : %v	", f.Name, f.Type)
    
    		// 获取字段值信息
    		// 通过interface{} 的 ValueOf()获取
    		// interface() 获取字段对应的值
    		val := v.Field(i).Interface()
    		fmt.Println("val: ", val)
    	}
    
    	// 获取方法
    	// NumMethod(), 获取方法个数
    	for i := 0; i < t.NumMethod(); i++ {
    		m := t.Method(i)
    		fmt.Println("方法名称: ", m.Name)
    		fmt.Println("方法类型: ", m.Type)
    	}
    }
    
    func main() {
    	u := User{1, "zs", 20}
    	reflect_struct(u)
    }
    

    查看匿名字段

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 定义结构体
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    type Boy struct {
    	User
    	Addr string
    }
    
    
    func main() {
    	m := Boy{User{1, "zs", 20}, "bj"}
    	t := reflect.TypeOf(m)
    	fmt.Println(t)
    	// 匿名
    	fmt.Printf("%#v
    ", t.Field(0))
    	// 值信息
    	fmt.Println("%#
    ", reflect.ValueOf(m).Field(0))
    }
    

    修改结构体值

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 定义结构体
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    // 修改结构体值
    func SetValue(i interface{}) {
    	v := reflect.ValueOf(i)
    	// 指针类型重新赋值
    	v = v.Elem()
    	// 取字段
    	f := v.FieldByName("Name")
    	if f.Kind() == reflect.String {
    		f.SetString("lisi")
    	}
    }
    
    func main() {
    	u := User{1, "zs", 20}
    	SetValue(&u)
    	fmt.Println(u)
    }
    

    调用方法

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    // 定义结构体
    type User struct {
    	Id   int
    	Name string
    	Age  int
    }
    
    func (u User) Hello(name string) {
    	fmt.Println("hello: ", name)
    }
    
    func main() {
    	u := User{1, "zs", 20}
    	v := reflect.ValueOf(u)
    	// 获取方法
    	m := v.MethodByName("Hello")
    	// 构建参数
    	args := []reflect.Value{reflect.ValueOf("wangwu")}
    	m.Call(args)
    }
    

    获取字段 tag

    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    type Student struct {
    	Name string `json:"name01" db:"name02"`
    }
    
    func main() {
    	var s Student
    	v := reflect.ValueOf(&s)
    	// 类型
    	t := v.Type()
    	// 获取字段
    	f := t.Elem().Field(0)
    	// 获取tag
    	fmt.Println(f.Tag.Get("json"))
    	fmt.Println(f.Tag.Get("db"))
    }
    
  • 相关阅读:
    golang 创建一个简单的连接池,减少频繁的创建与关闭
    go语言string、int、int64互相转换
    JVM中的STW和CMS
    如何避免后台IO高负载造成的长时间JVM GC停顿(转)
    NetScaler VLAN’s Demystified
    NetScaler SNIPs Bound To An Interface Without A VLAN
    NetScaler Best Practice With VMAC In A High Availability Configuration
    dashboard and reporting Interface analysis
    Windows远程桌面连接 出现身份错误 要求的函数不受支持
    ns统计使用资源的SNMP OID
  • 原文地址:https://www.cnblogs.com/zhichaoma/p/12510012.html
Copyright © 2011-2022 走看看