2019獨角獸企業重金招聘Python工程師標準>>>
反射reflection
- 可以大大提高程序的靈活性,使得interface{}有更大的發揮余地
- 反射可以使用TypeOf和ValueOf函數從接口中獲取目標對象信息
- 反射會將匿名字段作為獨立字段(匿名字段的本質)
- 想要利用反射修改對象狀態,前提是interface.data是settable,即pointer-interface
- 通過反射可以“動態”調用方法
常用的類型、函數和方法
//返回動態類型i的類型,如果i是一個空結構體類型,TypeOf將返回nil func TypeOf(i interface{}) Type//Type 接口類型 type Type interface {Align() intFieldAlign() int//指定結構體中方法的下標,返回某個方法的對象,需要注意的是返回的Method是一個獨立的結構體Method(int) Method/*type Method struct {Name stringPkgPath stringType TypeFunc ValueIndex int}*/MethodByName(string) (Method, bool)//返回該結構體類型的方法下標NumMethod() int//返回類型的名稱,即動態類型i的名稱Name() stringPkgPath() stringSize() uintptrString() stringKind() KindImplements(u Type) boolAssignableTo(u Type) boolConvertibleTo(u Type) boolComparable() boolBits() intChanDir() ChanDirIsVariadic() boolElem() Type//返回結構體類型第i個字段Field(i int) StructField//StructField結構體//type StructField struct {// Name string// PkgPath string// Type Type// Tag StructTag// Offset uintptr// Index []int// Anonymous bool//根據結構體字段索引獲取嵌入字段的結構體信息FieldByIndex(index []int) StructFieldFieldByName(name string) (StructField, bool)FieldByNameFunc(match func(string) bool) (StructField, bool)In(i int) TypeKey() TypeLen() int//返回動態類型i(結構體字段)的字段總數NumField() intNumIn() intNumOut() intOut(i int) Type }//返回接口i的一個初始化的新值.ValueOf(nil)返回一個零值 func ValueOf(i interface{}) Value// Value結構體 type Value struct {} // Value結構體的一些方法 // 返回結構體v中的第i個字段。如果v的類型不是結構體或者i超出了結構體的范圍,則會出現panic func (v Value) Field(i int) Value//以接口類型返回v的當前值 func (v Value) Interface() (i interface{}) //等價于. var i interface{} = (v's underlying value)//通過反射方式修改結構體對象的一些方法//返回接口v包含或者指針v包含的值 func (v Value) Elem() Value //判斷該接口v是否可以被set修改 func (v Value) CanSet() bool//使用另外一個反射接口去修改反射值 func (v Value) Set(x Value) //其他不同類型的Set func (v Value) SetBool(x bool) func (v Value) SetBytes(x []byte) func (v Value) SetFloat(x float64) func (v Value) SetInt(x int64) //設置結構體對象v的長度為n func (v Value) SetLen(n int) func (v Value) SetString(x string)//一些輔助方法 //返回反射結構體的Value的類型.如果v為零值,IsValid將返回false func (v Value) Kind() Kind //判斷value是否為有效值,通常用在判斷某個字段是否在反射體的Value中 func (v Value) IsValid() bool//Kind常量 type Kind uint const (Invalid Kind = iotaBoolIntInt8Int16Int32Int64UintUint8Uint16Uint32Uint64UintptrFloat32Float64Complex64Complex128ArrayChanFuncInterfaceMapPtrSliceStringStructUnsafePointer )
?
反射的基本操作
通過反射來獲取結構體字段的名稱以及其他相關信息。
package mainimport ("fmt""reflect"
)//定義結構體
type User struct {Id intName stringAge int
}//定義結構體方法
func (u User) Hello() {fmt.Println("Hello xuxuebiao")
}func main() {u := User{1, "bgops", 25}Info(u)u.Hello()
}//定義一個反射函數,參數為任意類型
func Info(o interface{}) {//使用反射類型獲取o的Type,一個包含多個方法的interfacet := reflect.TypeOf(o)//打印類型o的名稱fmt.Println("type:", t.Name())//使用反射類型獲取o的Value,一個空的結構體v := reflect.ValueOf(o)fmt.Println("Fields:")//t.NumField()打印結構體o的字段個數(Id,Name,Age共三個)for i := 0; i < t.NumField(); i++ {//根據結構體的下標i來獲取結構體某個字段,并返回一個新的結構體/**type StructField struct {Name stringPkgPath stringType TypeTag StructTagOf