reflect:在運(yùn)行時(shí)
動(dòng)態(tài)的獲取一個(gè)變量的類型信息和值信息,就叫反射
Type
反射中將類型劃分為兩種:
- 類型(Type):基礎(chǔ)類型和自定義類型
- 種類(Kind):底層的類型
// tk 顯示type和kind
func tk(x interface{}) {
t := reflect.TypeOf(x)
fmt.Printf("type: %v kind: %v \n", t.Name(), t.Kind())
}
// 自定義結(jié)構(gòu)體
type User struct {
Name string `json:"name"`
Gender int `json:"gender"`
}
user := User{
Name: "靜靜",
Gender: 0,
}
tk(user) // type: User kind: struct
type String string
var s String
tk(s) // type: String kind: string
// 基礎(chǔ)類型
var a float32
var b int
var c rune
tk(a) // type: float32 kind: float32
tk(b) // type: int kind: int
tk(c) // type: int32 kind: int32
需要注意的是Array宙帝、Slice丧凤、Map、Chan步脓、Ptr等類型的變量他們的type名稱都是空愿待,需要用Elem()獲取,如
// map
m := map[string]interface{}{}
tk(m) // type: kind: map
// 切片
arr := make([]interface{}, 0)
tk(arr) // type: kind: slice
// 指針
u := &user
tk(u) // type: kind: ptr
Value
定義一個(gè)struct來(lái)解釋
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
u := &User{}
- 獲取類型信息
t = reflect.TypeOf(u)
// 如果是指針靴患,獲取指向的變量
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
for i := 0; i < t.NumField(); i++ {
fmt.Printf("%s %s\n", t.Field(i).Name, t.Field(i).Type) // 打印字段名和字段類型
}
// 輸出如下:
// ID int
// Name string
- 獲取值信息
v = reflect.ValueOf(u)
// 如果是指針仍侥,獲取指向的變量
if v.Kind() == reflect.Ptr {
t = t.Elem()
}
for i := 0; i < v.NumField(); i++ {
fmt.Println(v.Field(i))
}
- 混著獲取
v := reflect.ValueOf(u)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
t := v.Type()
fmt.Println(t.Name())
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i).Interface()
switch value := value.(type) {
case int:
fmt.Printf("%6s: %v = %d\n", field.Name, field.Type, value)
case string:
fmt.Printf("%6s: %v = %s\n", field.Name, field.Type, value)
default:
}
}
- 封裝一個(gè)map轉(zhuǎn)struct的函數(shù)
// M2s map轉(zhuǎn)struct
// 根據(jù)struct的字段或者標(biāo)簽轉(zhuǎn)
func M2s(m map[string]interface{}, s interface{}) {
v := reflect.ValueOf(s)
if v.Kind() != reflect.Ptr {
panic("s must be a ptr")
}
// 從map獲取值
get := func(key, tag string) (value interface{}) {
for k, v := range m {
if k == key || k == tag {
value = v
break
}
}
return value
}
v = v.Elem()
length := v.NumField()
for i := 0; i < length; i++ {
value := get(v.Type().Field(i).Name, v.Type().Field(i).Tag.Get("json"))
if value != nil && v.Field(i).Kind() == reflect.ValueOf(value).Kind() {
v.Field(i).Set(reflect.ValueOf(value))
}
}
}