Go 反射示例

发布时间: 更新时间: 总字数:1718 阅读时间:4m 作者: IP上海 分享 网址

Go 反射示例项目,由于该部分比较复杂,仅从网上摘抄了一部分。

示例

package main

import (
	"fmt"
	"math/rand"
	"reflect"
	"strconv"
)

// Person 定义结构体和属性标签
type Person struct {
	FirstName string  `json:"first_name"`
	IsBoy     bool    `json:"is_boy"`
	Height    float32 `json:"height"`
}

func NewPersion(firstName string, isBoy bool, height float32) *Person {
	return &Person{FirstName: firstName, IsBoy: isBoy, Height: height}
}

// 定义String方法
func (p Person) String() string {
	return fmt.Sprintf("Person{FirstName: %s, IsBoy: %v, Height: %v}", p.FirstName, p.IsBoy, p.Height)
}

func (p Person) GetFirstName() string {
	return p.FirstName
}

func (p *Person) SetFirstName(firstName string) {
	p.FirstName = firstName
}

func (p Person) GetHeight() float32 {
	return p.Height
}

func (p *Person) SetHeight(height float32) {
	p.Height = height
}

// 接口
type Close interface {
	Close() error
}

type Addr struct {
	ip   string `json:"ip"`
	port int    `json:"port"`
}

func (addr Addr) GetIp() string {
	return addr.ip
}

func (addr Addr) GetPort() int {
	return addr.port
}

type Connection struct {
	Addr
	status int
}

func NewConnection(ip string, port int) *Connection {
	return &Connection{
		Addr{
			ip:   ip,
			port: port,
		},
		1,
	}
}

func (c *Connection) Send(msg string) error {
	fmt.Println("send", msg)
	return nil
}

func (c *Connection) Close() error {
	fmt.Printf("close %v:%v\n", c.ip, c.port)
	return nil
}

// 打印方法
func displayMethod(method reflect.Method, tab string) {
	// 获取方法接收者
	t := method.Type
	// 显示方法名
	fmt.Printf("%sfunc %s(", tab, method.Name)

	// 打印参数信息
	// 获取参数数量并遍历
	for i := 0; i < t.NumIn(); i++ {
		// 根据索引获取第i个参数的Type对象
		fmt.Printf("%s", t.In(i))
		if i != t.NumIn()-1 {
			fmt.Printf(", ")
		}
	}

	// 打印可变参数信息
	if t.IsVariadic() {
		fmt.Printf("...")
	}

	// 打印返回值信息
	fmt.Printf(") ")

	if t.NumOut() > 0 {
		fmt.Printf("(")

		// 获取返回值数量并遍历
		for i := 0; i < t.NumOut(); i++ {
			// 根据索引获取第i个返回值的Type
			fmt.Printf("%s", t.Out(i))
			if i != t.NumOut()-1 {
				fmt.Printf(", ")
			}
		}
		fmt.Printf(") ")
	}
	fmt.Printf("{}")
}

// 获取 reflect.Type 变量 t 的信息
func displayType(t reflect.Type, tab string) {
	// 判断 nil
	if t == nil {
		fmt.Println("nil")
		return
	}

	// 枚举判断每种类型
	switch t.Kind() {
	case reflect.Int, reflect.Float32, reflect.String, reflect.Bool:
		// 基本数据类型显示名称
		fmt.Printf("%s %s\n", tab, t.Name())
	case reflect.Array, reflect.Slice:
		// 针对数组和切片,打印类型
		fmt.Printf("%s %s\n", tab, t)
	case reflect.Map:
		// 对于映射类型,打印键和值
		fmt.Printf("%smap{\n", tab)
		fmt.Printf("%s\tKey: ", tab)
		// 获取键的Type对象
		fmt.Printf("%s %s", tab, t.Key())
		fmt.Println()
		fmt.Printf("%s\tValue: ", tab)
		// 获取键的Type对象
		fmt.Printf("%s %s", tab, t.Elem())
		fmt.Println()
		fmt.Printf("%s}", tab)
	case reflect.Func:
		// 对于函数类型,打印名字
		fmt.Printf("%sfunc (", tab)

		// 打印参数
		for i := 0; i < t.NumIn(); i++ {
			// 根据索引获取第i个参数的Type对象
			fmt.Printf("%s", t.In(i))
			if i != t.NumIn()-1 {
				fmt.Printf(", ")
			}
		}
		if t.IsVariadic() {
			fmt.Printf("...")
		}
		fmt.Printf(") ")

		// 打印返回值信息
		if t.NumOut() > 0 {
			fmt.Printf("(")
			// 变量返回值类型
			for i := 0; i < t.NumOut(); i++ {
				// 根据索引获取第i个返回值的Type对象
				fmt.Printf("%s", t.Out(i))
				if i != t.NumOut()-1 {
					fmt.Printf(", ")
				}
			}
			fmt.Printf(") ")
		}
		fmt.Printf("{}")
	case reflect.Struct:
		// 结构体,打印属性和方法
		fmt.Printf("%stype %s struct {", tab, t.Name())

		// 获取属性数量并遍历
		fmt.Printf("%s\tFields(%d):\n", tab, t.NumField())
		for i := 0; i < t.NumField(); i++ {
			// 获取第i个StructTag对象
			filed := t.Field(i)
			// 打印属性的Type对象和标签
			fmt.Printf("%s\t\t%s\t%s\t`%s`", tab, filed.Name, filed.Type, filed.Tag)
			fmt.Printf(",\n")
		}

		// 获取方法数量并遍历
		fmt.Printf("\n%s\tMethods(%d):\n", tab, t.NumMethod())
		for i := 0; i < t.NumMethod(); i++ {
			displayMethod(t.Method(i), tab+"\t\t")
			fmt.Printf(",\n")
		}
		fmt.Printf("%s}", tab)
	case reflect.Ptr:
		// 指针,遍历分析引用值
		fmt.Printf("%s*{\n", tab)
		// 获取指针的引用值,并递归调用 displayType 函数
		displayType(t.Elem(), tab+"\t")

		// 打印指针变量的方法
		if t.NumMethod() > 0 {
			fmt.Printf("\n%s\tMethods(%d):\n", tab, t.NumMethod())
			for i := 0; i < t.NumMethod(); i++ {
				// 打印方法信息
				displayMethod(t.Method(i), tab+"\t\t")
				if i != t.NumMethod()-1 {
					fmt.Printf(",\n")
				}
			}
		}
		fmt.Printf("}")
	default:
		fmt.Println("unknown", tab, t)
	}
}

// 获取 reflect.Type 变量 t 的Value信息
func displayValue(value reflect.Value, tab string) {
	// 获取值对应的枚举类型
	switch value.Kind() {
	case reflect.Int:
		fmt.Printf("%s[%s] %s", tab, value.Type(), strconv.FormatInt(value.Int(), 10))
	case reflect.Float32:
		fmt.Printf("%s[%s] %s", tab, value.Type(), strconv.FormatFloat(value.Float(), 'e', -1, 64))
	case reflect.String:
		fmt.Printf("%s[%s] %s", tab, value.Type(), value)
	case reflect.Bool:
		fmt.Printf("%s[%s] %s", tab, value.Type(), strconv.FormatBool(value.Bool()))
	case reflect.Array:
		fmt.Printf("%s[%s] {\n", tab, value.Type())

		// 获取数组的长度
		for i := 0; i < value.Len(); i++ {
			displayValue(value.Index(i), tab+"\t")
			fmt.Printf(",\n")
		}
		fmt.Printf("%s\n", tab)
	case reflect.Slice:
		// 针对切片,获取值对应的Type对象、长度和容量
		fmt.Printf("%s[%s](%d:%d) {\n", tab, value.Type(), value.Len(), value.Cap())

		// 获取切片长度
		for i := 0; i < value.Len(); i++ {
			displayValue(value.Index(i), tab+"\t")
			fmt.Printf("\n")
		}
		fmt.Printf("%s\n", tab)
	case reflect.Map:
		// 对于映射类型,获取值对应的Type对象
		fmt.Printf("%s[%s] {\n", tab, value.Type())

		it := value.MapRange()
		for it.Next() {
			displayValue(it.Key(), tab+"\t")
			fmt.Printf(" : ")
			displayValue(it.Value(), "")
			fmt.Printf(",\n")
		}
		fmt.Printf("%s}", tab)
	case reflect.Struct:
		// 结构体,获取值对应的type对象
		structType := value.Type()
		fmt.Printf("%s[%s] {\n", tab, structType)

		// 获取属性数量并遍历
		for i := 0; i < value.NumField(); i++ {
			structField := structType.Field(i)
			field := value.Field(i)
			fmt.Printf("%s\t%s:", tab, structField.Name)
			displayValue(field, tab+"\t")
			fmt.Printf(",\n")
		}
		fmt.Printf("%s}", tab)
	case reflect.Ptr:
		// 指针
		fmt.Printf("%s[%s] {\n", tab, value.Type())

		displayValue(value.Elem(), tab+"\t")
		fmt.Printf("}")
	default:
		fmt.Println("unknown", tab, value)
	}
}

func changeValue(value reflect.Value, path string) {
	switch value.Kind() {
	case reflect.Int:
		if value.CanSet() {
			fmt.Printf("int CanSet: %s.%s\n", path, value.Type())
			value.SetInt(value.Int() + rand.Int63n(100))
		}
	case reflect.Float32:
		if value.CanSet() {
			fmt.Printf("float32 CanSet: %s.%s\n", path, value.Type())
			value.SetFloat(value.Float() + rand.Float64())
		}
	case reflect.Bool:
		if value.CanSet() {
			fmt.Printf("bool CanSet: %s.%s\n", path, value.Type())
			value.SetBool(!value.Bool())
		}
	case reflect.String:
		if value.CanSet() {
			fmt.Printf("string CanSet: %s.%s\n", path, value.Type())
			value.SetString("chage:" + value.String())
		}
	case reflect.Array:
		if value.CanSet() {
			fmt.Printf("array CanSet: %s.%s\n", path, value.Type())
		}
		for i := 0; i < value.Len(); i++ {
			changeValue(value.Index(i), path+".array")
		}
	case reflect.Slice:
		for i := 0; i < value.Len(); i++ {
			changeValue(value.Index(i), path+".slice")
		}
	case reflect.Map:
		keys := value.MapKeys()
		for _, key := range keys {
			value.SetMapIndex(key, reflect.ValueOf("change:"+value.MapIndex(key).String()))
		}
	case reflect.Struct:
		if value.CanSet() {
			fmt.Printf("struct CanSet: %s.%s\n", path, value.Type())
		}
		for i := 0; i < value.NumField(); i++ {
			changeValue(value.Field(i), path+".struct")
		}
	case reflect.Ptr:
		if value.CanSet() {
			fmt.Printf("ptr CanSet: %s.%s\n", path, value.Type())
		}
		changeValue(value.Elem(), path+".point")
	default:
		fmt.Printf("unknown CanSet: %s.%s\n", path, value.Type())
	}
}

func callFunc(f reflect.Value) {
	ftype := f.Type()
	fmt.Printf("%s\n", ftype.String())

	parameters := make([]reflect.Value, 0)
	for i := 0; i < ftype.NumIn(); i++ {
		parameters = append(parameters, reflect.Zero(ftype.In(i)))
	}

	if ftype.IsVariadic() {
		fmt.Printf("%#v", f.CallSlice(parameters))
	} else {
		fmt.Println(f.Call(parameters))
	}
}

func callMethod(f reflect.Value, t reflect.Type, m reflect.Method) {
	ftype := f.Type()
	fmt.Printf("method: %s.%s => %s\n", t.Name(), m.Name, ftype.String())

	parameters := make([]reflect.Value, 0)
	for i := 0; i < ftype.NumIn(); i++ {
		parameters = append(parameters, reflect.New(ftype.In(i)).Elem())
	}

	if ftype.IsVariadic() {
		fmt.Printf("%#v", f.CallSlice(parameters))
	} else {
		fmt.Println(f.Call(parameters))
	}
}

func callValue(value reflect.Value) {
	fmt.Println("----------", value.Type())

	switch value.Kind() {
	case reflect.Array, reflect.Slice:
		for i := 0; i < value.Len(); i++ {
			callValue(value.Index(i))
		}
	case reflect.Map:
		it := value.MapRange()
		for it.Next() {
			callValue(it.Value())
		}
	case reflect.Struct:
		for i := 0; i < value.NumMethod(); i++ {
			callMethod(value.Method(i), value.Type(), value.Type().Method(i))
		}
	case reflect.Ptr:
		for i := 0; i < value.NumMethod(); i++ {
			callMethod(value.Method(i), value.Elem().Type(), value.Type().Method(i))
		}
	case reflect.Func:
		callFunc(value)
	default:
		fmt.Printf("unknown[%#v]\n", value)
	}
}

func main() {
	vars := make([]interface{}, 0, 20)
	var intV int = 1
	var floatV float32 = 3.14
	var boolV bool = true
	var stringV string = "hello world!"
	var arrayV [5]int = [...]int{1, 2, 3, 4, 5}
	var sliceV []string = []string{"i", "am", "string"}
	var mapV map[string]string = map[string]string{"name": "xianbin"}
	var funcV1 func(...interface{}) error = func(x ...interface{}) error {
		fmt.Println(x)
		return nil
	}
	var funcV2 func(string, int) *Connection = NewConnection
	var persionV *Person = NewPersion("xianbin", true, 1.8)
	var closeV Close

	vars = make([]interface{}, 0, 20)
	vars = append(vars, intV, &intV, floatV, boolV, stringV, arrayV, sliceV, mapV, funcV1, funcV2, persionV, *persionV, closeV)
	for _, v := range vars {
		displayType(reflect.TypeOf(v), "")
		displayValue(reflect.ValueOf(v), "")
		fmt.Println()
	}

	// 变量可修改条件
	// 对于基本数据类型变量可获取地址
	// 对于结构体属性必须是可获取地址且为公开的属性
	vars = append(vars, sliceV, mapV, *persionV, persionV, closeV)
	for _, v := range vars {
		changeValue(reflect.ValueOf(v), "")
		fmt.Println()
	}

	vars = make([]interface{}, 0, 20)
	var funcs []func() = make([]func(), 0)
	funcs = append(funcs,
		func() {
			fmt.Println("hello 1")
		},
		func() {
			fmt.Println("hello 2")
		})
	var funcV11 func(...interface{}) error = func(i ...interface{}) error {
		fmt.Println(i)
		return nil
	}
	var funcV12 func(string) error = func(i string) error {
		fmt.Println(i)
		return nil
	}
	vars = append(vars, funcs, funcV11, funcV12)
	for _, v := range vars {
		callValue(reflect.ValueOf(v))
		fmt.Println()
	}
}
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数