[go学习笔记]三十七、go语言中的反射(万能程序)

282 阅读1分钟

示例代码请访问:github.com/wenjianzhan…

关于“反射”你应该知道的

  • 提高了程序的灵活性
  • 降低了程序的可读性
  • 降低了程序的性能

示例代码

package ch36

import (
	"errors"
	"fmt"
	"reflect"
	"testing"
)

type Employee struct {
	EmployeeID string
	Name       string `format:"normal"`
	Age        int
}

type Customer struct {
	CookieID string
	Name     string
	Age      int
}

func TestDeepEqual(t *testing.T) {
	a := map[int]string{1: "one", 2: "two", 3: "three"}
	b := map[int]string{1: "one", 2: "two", 4: "three"}
	//t.Log(a == b)
	fmt.Println(reflect.DeepEqual(a, b))

	s1 := []int{1, 2, 3}
	s2 := []int{1, 2, 3}
	s3 := []int{2, 3, 1}

	t.Log("s1==s2?", reflect.DeepEqual(s1, s2))
	t.Log("s1==s2?", reflect.DeepEqual(s1, s3))
}

func TestFillNameAnfAge(t *testing.T) {
	settings := map[string]interface{}{"Name": "Mike", "Age": 40}
	e := Employee{}
	if err := fillBySettings(&e, settings); err != nil {
		t.Fatal(err)
	}
	t.Log(e)
	c := new(Customer)
	if err := fillBySettings(c, settings); err != nil {
		t.Fatal(err)
	}
	t.Log(*c)
}

func fillBySettings(st interface{}, settings map[string]interface{}) error {
	if reflect.TypeOf(st).Kind() != reflect.Ptr {
		if reflect.TypeOf(st).Elem().Kind() != reflect.Struct {
			return errors.New("the first param should be a pointer to the struct type")
		}
	}

	if settings == nil {
		return errors.New("settings is nil.")
	}

	var (
		field reflect.StructField
		ok    bool
	)

	for k, v := range settings {
		if field, ok = (reflect.ValueOf(st)).Elem().Type().FieldByName(k); !ok {
			continue
		}
		if field.Type == reflect.TypeOf(v) {
			vstr := reflect.ValueOf(st)
			vstr = vstr.Elem()
			vstr.FieldByName(k).Set(reflect.ValueOf(v))
		}
	}
	return nil
}

输出

=== RUN   TestFillNameAnfAge
--- PASS: TestFillNameAnfAge (0.00s)
    flexible_reflect_test.go:42: { Mike 40}
    flexible_reflect_test.go:47: { Mike 40}
PASS

Process finished with exit code 0

示例代码请访问:github.com/wenjianzhan…