Golang – 反射编程

反射编程会增加程序的复杂读和性能开销较大所以在使用的时候需要谨慎。通常使用反射编程都是灵活编程的需要。

package main

import (
	"errors"
	"fmt"
	"log"
	"reflect"
)

type Employee struct {
	EmployeeId int
	Name       string
	Age        int
}

type Customer struct {
	CustomerId int
	Name       string
	Age        int
}

// fillBySetting 函数接收一个结构体对象的指针和一个键值对的 map,
// 将 map 中的值填充到结构体对象的相应字段中
func fillBySetting(object interface{}, settings map[string]interface{}) error {
	// 判断 object 是否是指针类型
	if reflect.TypeOf(object).Kind() != reflect.Ptr {
		// 如果不是指针类型,判断 object 当中的元素是否是 struct 类型
		if reflect.TypeOf(object).Elem().Kind() != reflect.Struct {
			return errors.New("object 必须是 struct 类型")
		}
	}

	// 如果传入的 settings 是空的,就返回错误
	if settings == nil {
		return errors.New("settings 是空的")
	}

	// 遍历 settings map
	for k, v := range settings {
		// 检查 struct 中是否有对应的字段名
		field, ok := reflect.TypeOf(object).Elem().FieldByName(k)
		if !ok {
			continue // 如果没有对应字段,跳过
		}
		// 检查字段类型是否与传入值类型匹配
		if field.Type == reflect.TypeOf(v) {
			// 获取 struct 的值
			vstr := reflect.ValueOf(object)
			vstr = vstr.Elem() // 获取指针指向的元素
			// 设置 struct 中对应字段的值
			vstr.FieldByName(k).Set(reflect.ValueOf(v))
		}
	}
	return nil // 成功完成后返回 nil
}

func main() {
	// 创建一个 settings map
	settings := map[string]interface{}{"Name": "kiat", "Age": 11}
	e := Employee{}
	// 调用 fillBySetting 函数,填充 Employee 结构体
	err := fillBySetting(&e, settings)
	if err != nil {
		log.Fatalln(err)
	}
	// 打印填充后的 Employee 结构体
	fmt.Println(e)

	c := new(Customer)
	// 调用 fillBySetting 函数,填充 Customer 结构体
	err1 := fillBySetting(c, settings)
	if err1 != nil {
		log.Fatalln(err1)
	}
	// 打印填充后的 Customer 结构体
	fmt.Println(c)
}

输出结果:

{0 kiat 11}
&{0 kiat 11}

以下是使用Reflect找出 variable type

package main

import (
	"fmt"
	"reflect"
)

// checkType 函数检查传入的接口类型并打印其类型信息
func checkType(v interface{}) {
	// 获取传入变量的反射类型
	t := reflect.TypeOf(v)
	
	// 根据类型的种类进行判断
	switch t.Kind() {
	// 如果是浮点数类型
	case reflect.Float32, reflect.Float64:
		fmt.Println("float")
	// 如果是整数类型
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		fmt.Println("int")
	// 如果是其他类型
	default:
		fmt.Println("unknown", t)
	}
}

func main() {
	// 示例调用
	checkType(10)        // 输出: int
	checkType(3.14)      // 输出: float
	checkType("string")  // 输出: unknown string
}

Loading

Facebook评论