乐趣区

关于git:GO反射类实例

变量的外在机制

类型信息:是动态的元信息,是事后定义好的

值信息:是程序运行过程中动静扭转的

反射的应用

获取类型信息:reflect.TypeOf,是动态的

获取值信息:reflect.ValueOf,是动静的

反射获取 interface 值信息

package main

import (
    "fmt"
    "reflect"
)

// 反射获取 interface 值信息

func reflect_value(a interface{}) {v := reflect.ValueOf(a)
    fmt.Println(v)
    k := v.Kind()
    fmt.Println(k)
    switch k {
    case reflect.Float64:
        fmt.Println("a 是:", v.Float())
    }
}

func main() {
    var x float64 = 3.4
    reflect_value(x)
}

反射批改值信息

package main

import (
    "fmt"
    "reflect"
)

// 反射批改值
func reflect_set_value(a interface{}) {v := reflect.ValueOf(a)
    k := v.Kind()
    switch k {
    case reflect.Float64:
        // 反射批改值
        v.SetFloat(6.9)
        fmt.Println("a is", v.Float())
    case reflect.Ptr:
        // Elem() 获取地址指向的值
        v.Elem().SetFloat(7.9)
        fmt.Println("case:", v.Elem().Float())
        // 地址
        fmt.Println(v.Pointer())
    }
}

func main() {
    var x float64 = 3.4
    // 反射认为上面是指针类型,不是 float 类型
    reflect_set_value(&x)
    fmt.Println("main:", x)
}

构造体与反射

查看类型、字段和办法

package main

import (
    "fmt"
    "reflect"
)

// 定义构造体
type User struct {
    Id   int
    Name string
    Age  int
}

// 绑办法
func (u User) Hello() {fmt.Println("Hello")
}

// 传入 interface{}
func Poni(o interface{}) {t := reflect.TypeOf(o)
    fmt.Println("类型:", t)
    fmt.Println("字符串类型:", t.Name())
    // 获取值
    v := reflect.ValueOf(o)
    fmt.Println(v)
    // 能够获取所有属性
    // 获取构造体字段个数:t.NumField()
    for i := 0; i < t.NumField(); i++ {
        // 取每个字段
        f := t.Field(i)
        fmt.Printf("%s : %v", f.Name, f.Type)
        // 获取字段的值信息
        // Interface():获取字段对应的值
        val := v.Field(i).Interface()
        fmt.Println("val :", val)
    }
    fmt.Println("================= 办法 ====================")
    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}
    Poni(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)
    // Anonymous:匿名
    fmt.Printf("%#v\n", t.Field(0))
    // 值信息
    fmt.Printf("%#v\n", reflect.ValueOf(m).Field(0))
}

批改构造体的值

package main

import (
    "fmt"
    "reflect"
)

// 定义构造体
type User struct {
    Id   int
    Name string
    Age  int
}

// 批改构造体值
func SetValue(o interface{}) {v := reflect.ValueOf(o)
    // 获取指针指向的元素
    v = v.Elem()
    // 取字段
    f := v.FieldByName("Name")
    if f.Kind() == reflect.String {f.SetString("kuteng")
    }
}

func main() {u := User{1, "5lmh.com", 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, "5lmh.com", 20}
    v := reflect.ValueOf(u)
    // 获取办法
    m := v.MethodByName("Hello")
    // 构建一些参数
    args := []reflect.Value{reflect.ValueOf("6666")}
    // 没参数的状况下:var args2 []reflect.Value
    // 调用办法,须要传入办法的参数
    m.Call(args)
}

获取字段的 tag

package main

import (
    "fmt"
    "reflect"
)

type Student struct {Name string `json:"name1" db:"name2"`}

func main() {
    var s Student
    v := reflect.ValueOf(&s)
    // 类型
    t := v.Type()
    // 获取字段
    f := t.Elem().Field(0)
    fmt.Println(f.Tag.Get("json"))
    fmt.Println(f.Tag.Get("db"))
}

实例

办法

package common

import (
    "errors"
    "reflect"
    "strconv"
    "time"
)

// 依据构造体中 sql 标签映射数据到构造体中并且转换类型
func DataToStructByTagSql(data map[string]string, obj interface{}) {objValue := reflect.ValueOf(obj).Elem()
    for i := 0; i < objValue.NumField(); i++ {
        // 获取 sql 对应的值
        value := data[objValue.Type().Field(i).Tag.Get("sql")]
        // 获取对应字段的名称
        name := objValue.Type().Field(i).Name
        // 获取对应字段类型
        structFieldType := objValue.Field(i).Type()
        // 获取变量类型,也能够间接写 "string 类型"
        val := reflect.ValueOf(value)
        var err error
        if structFieldType != val.Type() {
            // 类型转换
            val, err = TypeConversion(value, structFieldType.Name()) // 类型转换
            if err != nil {}}
        // 设置类型值
        objValue.FieldByName(name).Set(val)
    }
}

// 类型转换
func TypeConversion(value string, ntype string) (reflect.Value, error) {
    if ntype == "string" {return reflect.ValueOf(value), nil
    } else if ntype == "time.Time" {t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
        return reflect.ValueOf(t), err
    } else if ntype == "Time" {t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
        return reflect.ValueOf(t), err
    } else if ntype == "int" {i, err := strconv.Atoi(value)
        return reflect.ValueOf(i), err
    } else if ntype == "int8" {i, err := strconv.ParseInt(value, 10, 64)
        return reflect.ValueOf(int8(i)), err
    } else if ntype == "int32" {i, err := strconv.ParseInt(value, 10, 64)
        return reflect.ValueOf(int64(i)), err
    } else if ntype == "int64" {i, err := strconv.ParseInt(value, 10, 64)
        return reflect.ValueOf(i), err
    } else if ntype == "float32" {i, err := strconv.ParseFloat(value, 64)
        return reflect.ValueOf(float32(i)), err
    } else if ntype == "float64" {i, err := strconv.ParseFloat(value, 64)
        return reflect.ValueOf(i), err
    }

    //else if ....... 减少其余一些类型的转换

    return reflect.ValueOf(value), errors.New("未知的类型:" + ntype)
}

调用

package main

import (
    "fmt"

    "github.com/student/1129/common"
)

//Product Product 定义一个构造体
type Product struct {
    ID           int64  `json:"id" sql:"id"`
    ProductClass string `json:"ProductClass" sql:"ProductClass"`
    ProductName  string `json:"ProductName" sql:"productName"`
    ProductNum   int64  `json:"ProductNum" sql:"productNum"`
    ProductImage string `json:"ProductImage" sql:"productImage"`
    ProductURL   string `json:"ProductUrl" sql:"productUrl" `
}

func main() {
    // 这块是模仿 mysql 获取单条的数据反射到构造体
    data := map[string]string{"id": "1", "ProductClass": "blog", "productName": "5lmh.com", "productNum": "40", "productImage": "http://www.5lmh.com/", "productUrl": "http://www.5lmh.com/"}
    productResult := &Product{}
    common.DataToStructByTagSql(data, productResult)
    fmt.Println(*productResult)
    // 这块是模仿 mysql 获取所有的数据反射到构造体
    Alldata := []map[string]string{{"id": "1", "ProductClass": "blog", "productName": "5lmh.com", "productNum": "40", "productImage": "http://www.5lmh.com/", "productUrl": "http://www.5lmh.com/"},
        {"id": "2", "ProductClass": "blog", "productName": "5lmh.com", "productNum": "40", "productImage": "http://www.5lmh.com/", "productUrl": "http://www.5lmh.com/"},
    }
    var productArray []*Product
    for _, v := range Alldata {Allproduct := &Product{}
        common.DataToStructByTagSql(v, Allproduct)
        productArray = append(productArray, Allproduct)
    }
    for _, vv := range productArray {fmt.Println(vv)
    }
}
退出移动版