美文网首页
Go语言学习笔记-反射和Unsafe

Go语言学习笔记-反射和Unsafe

作者: noonenote | 来源:发表于2019-05-14 16:19 被阅读0次

    reflect.TypeOf vs reflect.ValueOf

    • reflect.TypeOf 返回类型(reflect.Type)
    • reflect.ValueOf返回值(reflect.Value)
    • 可以从reflect.Value获得类型
    • 通过kind判断类型
    package reflect_test
    
    import (
        "fmt"
        "reflect"
        "testing"
    )
    
    func TestTypeAndValue(t *testing.T) {
        var f int64 = 10
        t.Log(reflect.TypeOf(f), reflect.ValueOf(f))
        t.Log(reflect.ValueOf(f).Type())
    }
    
    func CheckType(v interface{}) {
        t := reflect.TypeOf(v)
        switch t.Kind() {
        case reflect.Float32, reflect.Float64:
            fmt.Println("Float")
        case reflect.Int, reflect.Int32, reflect.Int64:
            fmt.Println("Integer")
        default:
            fmt.Println("Unknown", t)
        }
    }
    
    func TestBasicType(t *testing.T) {
        var f float64 = 12
        CheckType(&f)
    
    }
    
    func TestDeepEqual(t *testing.T) {
        a := map[int]string{1: "one", 2: "two", 3: "three"}
        b := map[int]string{1: "one", 2: "two", 3: "three"}
        //  t.Log(a == b)
        t.Log("a==b?", 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 == s3?", reflect.DeepEqual(s1, s3))
    
        c1 := Customer{"1", "Mike", 40}
        c2 := Customer{"1", "Mike", 40}
        fmt.Println(c1 == c2)
        fmt.Println(reflect.DeepEqual(c1, c2))
    }
    
    type Employee struct {
        EmployeeID string
        Name       string `format:"normal"`
        Age        int
    }
    
    func (e *Employee) UpdateAge(newVal int) {
        e.Age = newVal
    }
    
    type Customer struct {
        CookieID string
        Name     string
        Age      int
    }
    
    func TestInvokeByName(t *testing.T) {
        e := &Employee{"1", "Mike", 30}
        //按名字获取成员
        t.Logf("Name: value(%[1]v), Type(%[1]T) ", reflect.ValueOf(*e).FieldByName("Name"))
        if nameField, ok := reflect.TypeOf(*e).FieldByName("Name"); !ok {
            t.Error("Failed to get 'Name' field.")
        } else {
            t.Log("Tag:format", nameField.Tag.Get("format"))
        }
        reflect.ValueOf(e).MethodByName("UpdateAge").
            Call([]reflect.Value{reflect.ValueOf(1)})
        t.Log("Updated Age:", e)
    }
    

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

    package flexible_reflect
    
    import (
        "errors"
        "reflect"
        "testing"
    )
    
    func TestDeepEqual(t *testing.T) {
        a := map[int]string{1: "one", 2: "two", 3: "three"}
        b := map[int]string{1: "one", 2: "two", 3: "three"}
        //t.Log(a == b)
        t.Log(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 == s3?", reflect.DeepEqual(s1, s3))
    
    }
    
    type Employee struct {
        EmployeeID string
        Name       string `format:"normal"`
        Age        int
    }
    
    func (e *Employee) UpdateAge(newVal int) {
        e.Age = newVal
    }
    
    type Customer struct {
        CookieID string
        Name     string
        Age      int
    }
    
    func fillBySettings(st interface{}, settings map[string]interface{}) error {
    
        // func (v Value) Elem() Value
        // Elem returns the value that the interface v contains or that the pointer v points to.
        // It panics if v's Kind is not Interface or Ptr.
        // It returns the zero Value if v is nil.
    
        if reflect.TypeOf(st).Kind() != reflect.Ptr {
            return errors.New("the first param should be a pointer to the struct type.")
        }
        // Elem() 获取指针指向的值
        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
    }
    
    func TestFillNameAndAge(t *testing.T) {
        settings := map[string]interface{}{"Name": "Mike", "Age": 30}
        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)
    }
    

    相关文章

      网友评论

          本文标题:Go语言学习笔记-反射和Unsafe

          本文链接:https://www.haomeiwen.com/subject/bgzxnqtx.html