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
参考:
2. Go基础之--反射