这是一个分为2部分的博客系列文章的第1部分,该系列文章涉及Golang中的根据类型创建对象。 本部分讨论原始类型的创建。
Golang中的reflect包提供了必要的API,可根据要处理的对象的类型来更改程序的控制流。
反射包提供两个重要的结构Type
和Value
。
Type
是任何Go类型的表示。 即它可以用于编码任何Go类型(例如int
, string
, bool
, myCustomType
等)。 Value
表示任何Go值。 即它可以用于编码和操纵任何Go值。
类型与种类
Golang具有区分type
和kind
的隐藏的,鲜为人知的约定。 可以通过示例来理解区别。 考虑以下结构:
输入示例struct {
field1 type1
field2 type2
}
该结构的对象type
将是example
。 该对象的kind
为struct
。 可以将kind
视为type
的type
。
Golang中的所有结构都属于同一
kind
,但type
诸如Pointer
, Array
, Slice
, Map
等复合类型在type
和kind
之间进行了区分。
相反,诸如int
, float
, string
等原始类型不会区分kind
和type
。 即,一个int
变量的类型是int
。 一个int
变量的type
也是int
。
从类型创建对象
为了从类型签名创建对象,对象的type
和kind
都是必需的。 此后,当我使用“类型签名”一词时,是指该语言的reflect.Type
的reflect.Type
对象。
从原始类型创建原始对象
原始对象可以使用其零值从其类型签名中创建。
类型的零值是该类型的未初始化对象的值
这是Golang中所有原始类型的列表
布尔
整数
诠释8
16位
32位
整数64
维特
Uint8
Uint16
Uint32
Uint64
Uintptr
浮点32
浮动64
复杂64
复杂128
串
不安全指针
使用reflect.Zero
函数,可以创建基本类型的对象
func CreatePrimitiveObjects(t Reflection.Type)Reflection.Value {
返回reflect.Zero(t)
}
这将创建所需类型的对象,并返回与基础零值相对应的reflect.Value
对象。 为了使用该对象,需要提取其值。
可以使用适合每种原始类型的方法来提取对象的值。
提取整数值
Golang中有5种Integer类型:
整数
诠释8
16位
32位
整数64
整数类型表示平台定义的默认大小的整数。 接下来的4种类型分别是大小(以位为单位)为8、16、32和64的整数。
为了提取每种Integer类型,需要将代表Integer的reflect.Value
对象转换为适当的类型。
这是应如何提取int32
:
//提取Int32
func extractInt32(vreflect.Value)(int32,错误){
如果reflect.Kind()!= reflect.Int32 {
返回int32(0),errors.New(“无效输入”)
}
var intVal int64
intVal = v.Int()
返回int32(intVal),nil
}
请务必注意, reflect.Int()
始终返回int64
。 这是因为int64
可以对其中的所有其他Integer类型进行编码。
以下是应提取其余所有Integer类型的方法:
//提取Int64
func extractInt64(vreflect.Value)(int64,错误){
如果reflect.Kind()!= reflect.Int64 {
返回int64(0),errors.New(“无效输入”)
}
var intVal int64
intVal = v.Int()
返回intVal,无
}
//提取Int16
func extractInt16(vreflect.Value)(int16,错误){
如果reflect.Kind()!= reflect.Int16 {
返回int16(0),errors.New(“无效输入”)
}
var intVal int64
intVal = v.Int()
返回int16(intVal),nil
}
//提取Int8
func extractInt8(vreflect.Value)(int8,错误){
如果reflect.Kind()!= reflect.Int8 {
返回int8(0),errors.New(“无效输入”)
}
var intVal int64
intVal = v.Int()
返回int8(intVal),nil
}
//提取Int
func extractInt(vreflect.Value)(int,错误){
如果reflect.Kind()!= reflect.Int {
返回int(0),errors.New(“无效输入”)
}
var intVal int64
intVal = v.Int()
返回int(intVal),nil
}
提取布尔值
布尔值由反射包中的常量Bool
表示。
可以使用Bool()
方法从reflect.Value
对象中提取它们:
//提取布尔
func extractBool(vreflect.Value)(布尔值,错误){
如果reflect.Kind()!= reflect.Bool {
返回false,errors.New(“无效输入”)
}
返回v.Bool(),无
}
提取无符号整数
Golang中有5种无符号整数类型:
维特
Uint8
Uint16
Uint32
Uint64
Uint
类型表示平台定义的默认大小的无符号整数。 接下来的4种类型分别是大小(以位为单位)为8、16、32和64的无符号整数。
为了提取每种Unsigned Integer类型,需要将代表Unsigned Integer的reflect.Value
对象转换为适当的类型。
提取Uint32
方法如下:
//提取Uint32
func extractUint32(vreflect.Value)(uint32,错误){
如果reflect.Kind()!= reflect.Uint32 {
返回uint32(0),errors.New(“无效输入”)
}
var uintVal uint64
uintVal = v.Uint()
返回uint32(uintVal),nil
}
请务必注意, reflect.Uint()
始终返回uint64
。 这是因为uint64
可以对其中的所有其他Integer类型进行编码。
这是应提取其余无符号整数类型的方式
//提取Uint64
func extractUint64(vreflect.Value)(uint64,错误){
如果reflect.Kind()!= reflect.Uint64 {
返回uint64(0),errors.New(“无效输入”)
}
var uintVal uint64
uintVal = v.Uint()
返回uintVal,无
}
//提取Uint16
func extractUint16(vreflect.Value)(uint16,错误){
如果reflect.Kind()!= reflect.Uint16 {
返回uint16(0),errors.New(“无效输入”)
}
var uintVal uint64
uintVal = v.Uint()
返回uint16(uintVal),nil
}
//提取Uint8
func extractUint8(vreflect.Value)(uint8,错误){
如果reflect.Kind()!= reflect.Uint8 {
返回uint8(0),errors.New(“无效输入”)
}
var uintVal uint64
uintVal = v.Uint()
返回uint8(uintVal),nil
}
//提取Uint
func extractUint(vreflect.Value)(uint,错误){
如果reflect.Kind()!= reflect.Uint {
返回uint(0),errors.New(“无效输入”)
}
var uintVal uint64
uintVal = v.Uint()
返回uint(uintVal),无
}
提取浮点数
Golang中有2种浮点数类型:
浮点32
浮动64
Float32
类型表示大小为32位的浮点数。 Float64
类型表示大小为64位的浮点数。
为了提取每种浮点数类型,需要将表示浮点数的reflect.Value
对象转换为适当的类型。
提取Float32
方法如下:
//提取Float32
func extractFloat32(vreflect.Value)(float32,错误){
如果reflect.Kind()!= reflect.Float32 {
返回float32(0),errors.New(“无效输入”)
}
var floatVal float64
floatVal = v.Float()
返回float32(floatVal),nil
}
请务必注意, reflect.Float()
始终返回float64
。 这是因为float64
可以对其中的所有其他浮点数类型进行编码。
这是应如何提取64位浮点数值的方法
//提取Float64
func extractFloat64(vreflect.Value)(float64,错误){
如果reflect.Kind()!= reflect.Float64 {
返回float64(0),errors.New(“无效输入”)
}
var floatVal float64
floatVal = v.Float()
返回floatVal,nil
}
提取复杂值
Golang有2种复杂类型:
复杂64
复杂128
Complex64
类型表示大小为Complex64
复数。 Complex128
类型表示大小为128位的复数。
为了提取每种Complex类型,需要将表示Complex值的reflect.Value
对象转换为适当的类型。
这是应提取Complex64
方法:
//提取Complex64
func extractComplex64(vreflect.Value)(complex64,错误){
如果reflect.Kind()!= reflect.Complex64 {
返回complex64(0),errors.New(“无效输入”)
}
var complexVal complex128
complexVal = v.Complex()
返回complex64(complexVal),无
}
请务必注意, reflect.Complex()
始终返回complex128
。 这是因为complex128
可以对其中的所有其他Complex类型进行编码。
这是应如何提取128位Complex值的方法
//提取Complex128
func extractComplex128(vreflect.Value)(complex128,错误){
如果reflect.Kind()!= reflect.Complex128 {
返回complex128(0),errors.New(“无效输入”)
}
var complexVal complex128
complexVal = v.Complex()
返回complexVal,无
}
提取字符串值
字符串值由反射包中的常量String
表示。
可以使用对象的String()
方法从reflect.Value
对象中提取它们。
提取String
方法如下:
//提取字符串
func extractString(vreflect.Value)(字符串,错误){
如果reflect.Kind()!= reflect.String {
返回“”,errors.New(“无效输入”)
}
返回v.String(),无
}
提取指针值
Golang中有2种Pointer类型:
Uintptr
不安全指针
Uintptr
和UnsafePointer
只是表示过程内存中虚拟地址的uint
值。 它可以表示变量或函数的位置。
Uintptr
和UnsafePointer
之间的区别在于, Uintptr
由Go运行时进行类型检查,而UnsafePointer
没有。 UnsafePointer
的内存布局兼容,则可用于将任何Go类型转换为任何其他Go类型。 如果您想探索这个问题,请在下面评论,我将在上面写更多。
可以分别使用Addr()
方法和UnsafeAddr()
方法从reflect.Value
对象中提取reflect.Value
和UnsafeAddr()
。 这是显示应如何提取Uintptr
的示例
应该以这种方式提取Uintptr //提取Uintptr
func extractUintptr(vreflect.Value)(uintptr,错误){
如果reflect.Kind()!= reflect.Uintptr {
返回uintptr(0),errors.New(“无效输入”)
}
var ptrVal uintptr
ptrVal = v.Addr()
返回ptrVal,nil
}
这是应提取UnsafePointer
值的方式
//提取UnsafePointer
func extractUnsafePointer(vreflect.Value)(unsafe.Pointer,错误){
如果reflect.Kind()!= reflect.UnsafePointer {
返回unsafe.Pointer(0),errors.New(“无效输入”)
}
var unsafeVal unsafe.Pointer
unsafeVal = unsafe.Pointer(v.UnsafeAddr())
返回unsafeVal,无
}
重要的是要注意上面的v.UnsafeAddr()
返回一个uintptr
值。 它应该在同一行中进行类型转换,否则unsafe.Pointer
值可能未指向预期的位置。
请注意,应在不检查kind
情况下使用reflect.Value
结构的任何方法,因为它很容易引起panic
。
在下一篇博客文章中,我将写有关创建更复杂的类型(如struct
, pointer
, chan
, map
, slice
, array
等)的文章。 敬请关注!