若是传入的是一个接口,若是是动态绑定了一个实现结构体的,则显示具体结构体的Type,不然是接口的名字。这个方法返回的是一个Type接口,其实就是返回了 绑定类型的rtype,这个指针在Value这个结构体有json
a:=A{} a.age=19 a.name="PB" i:=1 log.Println(reflect.TypeOf(a).Name()) //类型的名字 A log.Println(reflect.TypeOf(i).Name()) //int //底层基础类型 log.Println(reflect.TypeOf(a).Kind(),reflect.TypeOf(i).Kind()) //struct int log.Println(reflect.TypeOf(a).Kind().String()=="struct") //true //返回的是Kind类型 须要经过string转化 不然是一个uint类型
Typeof返回的是一个Type接口下面看看Type接口有哪些实现函数
type Student struct { name string `pb:"名字"` age int `json:"年龄"` } type Part1 struct { a bool b int32 //4 byte c int8 d int64 e byte } type Part2 struct { e byte c int8 a bool b int32 d int64 }
利用反射能够查看结构体或其余类型的内存分配状况,如内存大小,字节对齐的大小等....布局
http://www.fly63.com/article/detial/7405 性能
为何要字节对齐?ui
加快访问速度,减小读取次数。若是不对齐,那么一个数据的地址可能会分散到用两个字节,那么CPU就可能须要分两次读取。this
咱们假设CPU以4字节为单位读取内存。指针
若是变量在内存中的布局按4字节对齐,那么读取a变量只须要读取一次内存,即word1;读取b变量也只须要读取一次内存,即word2。code
而若是变量不作内存对齐,那么读取a变量也只须要读取一次内存,即word1;可是读取b变量时,因为b变量跨越了2个word,因此须要读取两次内存,分别读取word1和word2的值,而后将word1偏移取后3个字节,word2偏移取前1个字节,最后将它们作或操做,拼接获得b变量的值。orm
显然,内存对齐在某些状况下能够减小读取内存的次数以及一些运算,性能更高。对象
另外,因为内存对齐保证了读取b变量是单次操做,在多核环境下,原子性更容易保证。
可是内存对齐提高性能的同时,也须要付出相应的代价。因为变量与变量之间增长了填充,并无存储真实有效的数据,因此占用的内存会更大。这也是一个典型的空间换时间的应用场景。
- 增长CPU吞吐量,减小读取次数
- 保证原子操做
- 空间换时间,若是没有安排好内存的话,中间会多出不少空白
part1
part2
func main(){ s1 := Student{"pb", 12} type_s1 := reflect.TypeOf(s1) type_part1 := reflect.TypeOf(Part1{}) type_part2 := reflect.TypeOf(Part2{}) //关于内存 log.Println(type_s1.Align(), type_part1.Align()) //8 8 log.Println(type_s1.FieldAlign(), type_part1.FieldAlign()) //8 8 log.Println(type_part1.Size(), type_part2.Size()) //32 16 why?上图 }
type MyMap map[int]string log.Println(reflect.TypeOf(MyMap{}).Key()) //返回map类型 key的类型 int log.Println(reflect.TypeOf(MyMap{}).Elem()) //返回 容器类型中元素的类型 string //It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
反射方法。第一个传入0 1 2来表示方法 后面那个传入字符串
反射属性,Tag属性能够得到属性后面的注解调用Get方法
这是一个结构体,能够操做对象的值,每一个方法都返回Value来达到链式调用的目的,
Type能实现的功能Value均可以
type Value struct { typ *rtype //Typeof返回的东西 继承了Type接口 保存了一个数据的类型和底层指针 ptr unsafe.Pointer flag } type rtype struct { size uintptr ptrdata uintptr // number of bytes in the type that can contain pointers hash uint32 // hash of type; avoids computation in hash tables tflag tflag // extra type information flags align uint8 // alignment of variable with this type fieldAlign uint8 // alignment of struct field with this type kind uint8 // enumeration for C alg *typeAlg // algorithm table gcdata *byte // garbage collection data str nameOff // string form ptrToThis typeOff // type for pointer to this type, may be zero }
type Stu struct { name string "名字" age int "年龄" } func (s *Stu) Say() { fmt.Println(s.name) } func (s Stu) Hello() { fmt.Println(s.name) } func (s Stu) Hello2(ss string,i int) { fmt.Println(ss,i) }
s := Stu{"pb", 12} v := reflect.ValueOf(s) fmt.Println(v,v.Field(0)) fmt.Println(v.Kind(), v.Type().Name()) fmt.Println(v.FieldByName("name"), v.Field(0)) //操做方法 方法位置按照函数名字进行字典序排序 v.Method(0).Call(nil) //#调用无参函数 v.Method(1).Call([]reflect.Value{reflect.ValueOf("OK"), reflect.ValueOf(1)}) //#调用有参函数 必须是Value类型
要修改对象的值,必须指针的Value调用Elem方法才能够修改
只能指针的Value(包括动态绑定的接口,若是这个接口的值是指针类型也可)才能够调用而且修改原来对象的值
s = Stu{Name:"biningo",age:18} sv:=reflect.ValueOf(s) log.Println(sv.Field(0)) pv:=reflect.ValueOf(&s) //// It panics if v's Kind is not Interface or Ptr. //log.Println(reflect.ValueOf(s).Elem().CanSet()) log.Println(pv.Elem().Field(0),pv.Elem().Field(0).CanSet()) //biningo true pv.Elem().Field(0).SetString("BININGO") log.Println(pv.Elem().Field(1).CanSet()) //false 必需要大写的字段才能够设置 log.Println(s) //BININGO 18 //对于没有接口的类型来讲 返回的就是一个指针 i:=pv.Interface() //返回空接口 //Valueof返回的是实际动态绑定的类型 这里是*Stu log.Println(reflect.ValueOf(i).Elem().CanSet()) //true 若是不加Elem则false
Type和Value能够相互转化
经过Type来建立一个Value
t:=sv.Type() //Value->Type log.Println(t.Name()) //Stu //Type建立Value s2:=reflect.New(t) log.Println(s2.Type(),s2.Elem().CanSet(),s2) //true由于返回的是*Stu 都是默认值 s2.Elem().Field(0).SetString("Biningo2") //s2.Elem().Field(1).SetInt(19) 私有字段不可设置 log.Println(s2)
Value能够直接转化为Type
调用Value的Type方法便可
Value转化为具体对象
Value-->Interface-->Obj
//Value转化为具体对象 //Value-->Interface-->Obj inter:=sv.Interface() //*Stu s1:=inter.(Stu) log.Println(s1) // biningo 18