golang之reflection

反射就是程序能够在运行时检查变量和值,求出它们的类型。

reflect包实现运行时反射。

创建一个接收任何数据类型任何数值的查询string:

func createQuery(q interface{}) string {
}

reflect.Type 表示 interface{} 的具体类型,而 reflect.Value 表示它的具体值。reflect.TypeOf() 和 reflect.ValueOf() 两个函数可以分别返回 reflect.Type 和 reflect.Value。TypeOf获得对象的类型信息,如该类型(结构体)有什么字段,字段类型,ValueOf获得对象的运行时表示,如有什么字段,字段的值是什么。

Type 表示 interface{} 的实际类型(在这里是 main.Order),而 Kind 表示该类型的特定类别(在这里是 struct)。

NumField() 方法返回结构体中字段的数量,而 Field(i int) 方法返回字段 i 的 reflect.Value注:NumField()仅适用于结构体类别。

func createQuery(q interface{}) {
    if reflect.ValueOf(q).Kind() == reflect.Struct {
        v := reflect.ValueOf(q)
        fmt.Println("Number of fields", v.NumField())
        for i := 0; i < v.NumField(); i++ {
            fmt.Printf("Field:%d type:%T value:%v\n", i, v.Field(i), v.Field(i))
        }
    }
}

获取变量的值

reflect.ValueOf(x).Float()
reflect.ValueOf(x).Int()
reflect.ValueOf(x).String()
reflect.ValueOf(x).Bool()

Int 和 String 可以分别取出 reflect.Value 作为 int64 和 string的值。

修改变量的值

reflect.Value.SetXX相关方法,如:
reflect.Value.SetFloat():设置浮点数
reflect.Value.SetInt():设置整数
reflect.Value.SetString():设置字符串

 注意这里的reflect.Value必须是指针类型才会生效,需要借助Elem()方法(fv.Elem().SetFloat(3.14))。

// 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.
func (v Value) Elem() Value;
package main

import (
    "reflect"
    "fmt"
)

func main() {
    var a float64
    fmt.Println(a)
    fv := reflect.ValueOf(&a)
    fv.Elem().SetFloat(3.14)
    fmt.Println(a)
}
-----------------------------

0
3.14

func PrintFieldName(val interface{}){
    v := reflect.ValueOf(val)  // 这是指针的发射
    ele := v.Elem()  // 获取指针指向的结构体
    t := ele.Type()  // 获取指针指向的结构体的类型信息

    numField := t.NumField()
    for i:=0; i < numField; i++ {
        field := t.Field(i)
        fieldValue := ele.Field(i)   // 用指针执行的结构体来访问
        if fieldValue.CanSet() {
            fieldValue.Set()
        }
    }
}    
package main
import (
    "fmt"
    "reflect"
)

type order struct {
    ordId int
    customerId int
}

type employee struct{
    name    string
    id      int
    address string
    salary  int
    country string
}

func createQuery(q interface{}){
    if reflect.ValueOf(q).Kind() == reflect.Struct {
        t := reflect.TypeOf(q).Name()
        query := fmt.Sprintf("insert into %s values(", t)
        v := reflect.ValueOf(q)
        for i:=0; i < v.NumField(); i++{
            switch v.Field(i).Kind(){
            case reflect.Int:
                if i == 0{
                    query = fmt.Sprintf("%s%d", query, v.Field(i).Int())
                } else {
                    query = fmt.Sprintf("%s, %d", query, v.Field(i).Int())
                }
            case reflect.String:
                if i==0 {
                    query = fmt.Sprintf("%s\"%s\"", query, v.Field(i).String())
                } else {
                    query = fmt.Sprintf("%s, \"%s\"", query, v.Field(i).String())
                }
            default:
                fmt.Println("Unsupported type")
                return
            }
        }
        query = fmt.Sprintf("%s)", query)
        fmt.Println(query)
        return
    }
    fmt.Println("Unsupported type")
}
func main(){
    o := order{
        ordId: 44,
        customerId: 100,
    }
    createQuery(o)

    e := employee{
        name:       "Wang",
        address:    "HN",
        country:    "CN",
        id:         10000,
        salary:     10000,
    }
    createQuery(e)

    i := 100
    createQuery(i)
}
output:
insert into order values(44, 100)
insert into employee values("Wang", 10000, "HN", 10000, "CN")
Unsupported type

 

参考:

1.         Go 系列教程 —— 34. 反射

2.         Go基础之--反射

posted @ 2019-07-03 20:58  yuxi_o  阅读(246)  评论(0编辑  收藏  举报