Reflect-Go一分鐘快速入門

Reflect

本文側重講解reflect反射的實踐應用,適合新手初窺門徑。html

reflect兩個基本功能

  • reflect.TypeOf() 動態獲取輸入數據的類型
  • reflect.ValueOf() 動態獲取輸入數據的值
func TypeOf(i interface{}) Type func ValueOf(i interface{}) Value 複製代碼

經過reflect.Type和reflect.Value支持的方法,能夠對輸入的動態數據進行解析。 那麼瞭解reflect.Type和reflect.Value提供的方法尤其重要,由於比較多,此介紹放在文末。golang

reflect.Kind

在reflect.Type和reflect.Value上調用Kind()方法,能夠獲得reflect.Kind類型值,從而知道動態數據的類型。這個是動態解析的鑰匙,經過反射後拿到具體的類型才能作相應的工做,逐層解析。bash

const (
	Invalid Kind = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	Array
	Chan
	Func
	Interface
	Map
	Ptr
	Slice
	String
	Struct
	UnsafePointer
)
複製代碼

解析流程

  • Ptr指針和Interface 經過調用Elem()方法獲得指向元素的值,再進入循環解析。
  • Slice、Array、Map、Struct複合數據類型,經過各自的方法拿到他們組成類型值,再進入循環解析
  • 直到爲基礎數據類型或者Func、Chan、UnsafePointer。
    reflect解析動態數據流程

具體類型解析

下述demo中默認函數

rt = reflect.TypeOf(data)
rv = reflect.ValueOf(data)
複製代碼

Struct

//遍歷結構體的Field
for i := 0; i < rt.NumField(); i++ {
    rt.Field(i) //第i個Field的StructField
    rv.Filed(i) //第i個Field的Value
}

//遍歷結構體的方法
for i := 0; i < rt.NumMethod(); i++ {
    rt.Method(i) //第i個方法的Method
    rv.Method(i) //第i個方法的Value
}
複製代碼

Map

//遍歷Map的key和value
for _, key := range rv.MapKeys() {
    //其中key爲鍵的Value
    rv.MapIndex(key) //鍵值的Value
}

rv.Len() //map的大小
rv.SetMapIndex() //map索引賦值
複製代碼

Slice Array

//遍歷Slice或者Array
for i := 0; i < rv.Len(); i++ {
    rv.Index(i) //子元素的Value
}

rv.Cap()    //獲取切片或者Array容量
rv.SetCap(i) //調整切片容量
rv.Slice(i, j) //返回切片s[i:j]的Value
複製代碼

Ptr Interface

if !rv.IsNil() {
    rv.Elem() //指針或者interface實際指向元素
}
複製代碼

Bool Int Unit Float Complex String

rv.Bool() //返回bool
rv.Int() //返回int64
rv.Uint() //返回uint64
rv.Float() //返回float64
rv.Complex() //返回complex128
rv.Sting() //返回string

//修改Value結構中的值,必須類型一致
rv.Set()
rv.SetBool() 
rv.SetInt() 
rv.SetUint() 
rv.SetFloat() 
rv.SetComplex() 
rv.SetString()
rv.SetBytes()
複製代碼

Func Chan UnsafePointer

動態解析的時候,用得比較少,這裏就不說了ui

Type和Value方法

Type和Value擁有的同名方法

Method Type返回類型 Value返回類型 備註
Kind Kind Kind 返回指定對象的Kind類型
NumMethod int int 返回struct擁有的方法總數,包括unexported方法
MethodByName Method Value 根據方法名找方法
Method Method Value 返回第i個方法
NumField int int 返回struct所包含的field數量
Field StructField Value 取struct結構的第n個field
FieldByIndex StructField Value 嵌套的方式取struct的field,好比v.FieldByIndex([]int{1,2})等價於 v.field(1).field(2)
FieldByName StructFiel,bool Value 返回名稱匹配match函數的field
FieldByNameFunc StructField,bool Value 返回名稱匹配match函數的field

Type獨有的方法

Method 備註
Align 分配內存時的內存對齊字節數
FieldAlign 做爲struct的field時內存對齊字節數
Name type名 string類型
PkgPath 包路徑, "encoding/base64", 內置類型返回empty string
Size 該類型變量佔用字節數
String type的string表示方式
Implements 判斷該類型是否實現了某個接口
AssignableTo 判斷該類型可否賦值給某個類型
ConvertibleTo 判斷該類型可否轉換爲另一種類型
Comparable 判斷該類型變量是否能夠比較
ChanDir 返回channel的方向 recv/send/double
IsVariadic 判斷函數是否接受可變參數
Elem 取該類型的元素
In 函數第n個入參
Out 函數第n個出參
NumIn 函數的入參數個數
NumOut 函數的出參個數
Key 返回map結構的key類型Type
Len 返回array的長度

Value獨有的方法

Method 備註
Addr v的指針,前提時CanAddr()返回true
Bool 取值,布爾類型
Bytes 取值,字節流
Call 調用函數
CallSlice 調用具備可變參的函數
CanAddr 判斷可否取址
CanInterface 判斷Interface方法可否使用
CanSet 判斷v的值可否改變
Cap 判斷容量 Array/Chan/Slice
Close 關閉Chan
Complex 取值,複數
Convert 返回將v轉換位type t的結果
Elem 返回interface包含或者Ptr指針的實際值
Float 取值,浮點型
Index 索引操做 Array/Slice/String
Int 取值,整型
Interface 將當前value以interface{}形式返回
IsNil 判斷是否爲nil,chan, func, interface, map, pointer, or slice value
IsValid 是不是可操做的Value,返回false表示爲zero Value
Len 適用於Array, Chan, Map, Slice, or String
MapIndex 對map類型按key取值
MapKeys map類型的全部key的列表
OverflowComplex 溢出判斷
OverflowFloat 溢出判斷
OverflowInt 溢出判斷
OverflowUint 溢出判斷
Pointer 返回uintptr 適用於slice
Recv chan接收
Send chan發送
Set 將x賦值給v,類型要匹配
SetBool Bool賦值,須要先判斷CanSet()爲true
SetBytes Bytes賦值
SetCap slice調整切片容量
SetMapIndex map索引賦值
SetUint Unit賦值
SetPointer unsafe.Pointer賦值
SetString String賦值
Slice return v[i:j] 適用於Array/Slict/String
String return value的string表示方法
TryRecv chan非阻塞接收
TrySend chan非阻塞發送
Type 返回value的Type
UnsafeAddr 返回指向value的data的指針

引用連接

Type和Value方法: www.cnblogs.com/ksir16/p/90…spa

相關文章
相關標籤/搜索