变量和常量
变量和常量
- 使用一个名称来绑定一块内存地址,该内存地址中存放的数据类型由定义变量时指定的类型决定
- 变量:该内存地址里面存放的内容可以改变
- 常量:该内存地址里面存放的内容不可以改变
- 常量存储在程序的只读段中(.rodata section)
- 存储和生存期:
- Go语言提供自动内存管理,通常程序员不需要特别关注变量的生存期和存放位置
- 编译器使用栈逃逸技术能够自动为变量分配空间
反射的API
-
所有类型通用的方法,对于未命名类型返回为空
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// 返回包含包名的类型名字,对于未命名类型返回的是空 Name() string // Kind返回该类型的底层基础类型,和底层类型不同,底层类型关注的是赋值和类型转化问题的。 Kind() Kind // 确定当前类型是否实现了u接口类型 // 注意这里的u必须是接口类型的Type Implements(u Type) bool // 判断当前类型的实例是否能赋值给type为u的类型变量 (和底层类型相关) AssignableTo(u Type) bool // 判断当前类型的实例是否能强制类型转换为u类型变量 ConvertibleTo(u Type) bool // 判断当前类型是否支持比较 // 支持比较的类型可以作为map的key Comparable() bool // 返回一个类型的方法的个数 NumMethod() int // 通过索引值访问方法,索引值必须属于[0, NumMethod()],否则引发panic Method(int) Method // 通过方法名获取Method MethodByName(string) (Method, bool) // 返回类型的包路径,如果类型是预声明类型或者未命名类型,则返回空字符串 PkgPath() string // 返回存放该类型的实例需要多大的字节空间 Size() uintptr
-
不同基础类型(底层基础类型)的专有方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// Int*, Uint*, Float*, Complex*: Bits // Array: Elem, Len // Chan: ChanDir, Elem // Func: In, NumIn, Out, NumOut, IsVariadic. // Map: Key, Elem // Ptr: Elem // Slice: Elem // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField // 返回类型的元素类型,该方法只适合Array、Chan、Map、Ptr、Slice类型 Elem() Type // 返回数值型类型内存占用的位数 Bits() int // struct类型专有的方法 // 返回字段数目 NumField() int // 通过整数索引获取struct字段 Field(i int) StructField // 获取嵌入字段获取struct字段 FieldByIndex(index []int) StructField // 通过名字查找获取struct字段 FieldByName(name string) (StructField, bool) // func类型专有的方法 // 函数是否是不定参数函数 IsVariadic() bool // 输入参数个数 NumIn() int // 返回值个数 NumOut() int // 返回第i个输入参数类型 In(i int) Type // 返回第i个返回值类型 Out(i int) Type // map类型专用的方法 // 返回map key的type Key() Type
- 从实例到Value 通过实例获取Value对象,直接使用reflect.ValueOf()函数,例如:
|
|
- 从实例到Type 通过实例获取反射对象的Type,直接使用reflect.TypeOf()函数,例如:
|
|
- 从Type到Value Type里面只有类型信息,所以直接从一个Type接口变量里面是无法获得实例的Value的,但是 可以通过该Type构建一个新实例的Value。reflect包提供了两种方法,示例如下:
如果知道一个类型值的底层存放地址,则还有一个函数是可以依据Type和该地址值恢复出Value的,例如
|
|
- 从Value到Type 从反射对象Value到Type可以直接调用Value的方法,因为Value内部存放看到Type类型的指针,例如:
|
|
- 从Value到实例 Value本身就包含类型和值信息,reflect提供了丰富的方法来实现从Value到实例的转换。 例如:
- 从Value的指针到值 从一个指针类型的Value获取值类型Value有两种方法,示例如下:
- Type指针和值的相互转换 (1) 指针类型Type到值类型Type,例如
(2) 值类型Type到指针类型的Type,例如
- Value值的可修改性 Value值的修改涉及如下两个方法
Value值在什么时候可以修改?我们知道实例对象传递给接口的是一个完全的值拷贝,如果 调用反射的方法reflect.ValueOf()传递去的是一个值类型变量,则获得的Value实际上是 原对象的一个副本,这个Value是无论如何也不能被修改的。如果传递去的是一个指针, 虽然接口内部转换的也是指针的副本,但通过指针还是可以访问到最原始的对象, 所以,此种情况获得的Value是可以修改的。