go 反射粗略理解

go 里面反射 两个很重要的类型,reflect.Type ,reflect.Value ,接下来着重根据这两种类型谈谈自己的简单理解。

reflect.Type

go 反射粗略理解_第1张图片
reflect.Type 里的子类型structType包含了StructField,通过 Field(i int) StructField 方法可获得,StructField就是结构体的属性字段的反射对象。
注意如果reflect.TypeOf()传入指针类型,那么获取的type类型不是structType此时需要调用Elem()转换为structType
看看StructField 里面有啥。

	// A StructField describes a single field in a struct.
type StructField struct {
	// Name is the field name.
	Name string
	// PkgPath is the package path that qualifies a lower case (unexported)
	// field name. It is empty for upper case (exported) field names.
	// See https://golang.org/ref/spec#Uniqueness_of_identifiers
	PkgPath string

	Type      Type      // field type
	Tag       StructTag // field tag string
	Offset    uintptr   // offset within struct, in bytes
	Index     []int     // index sequence for Type.FieldByIndex
	Anonymous bool      // is an embedded field
}

其实通过源码里的注释已经可以很清晰的看到,字段的反射对象里包含了StructTag对象,也可以判断是否是嵌入类型,以及如果是私有属性,PkgPath应该有路径值等信息。
看看 StructTag 对象怎么写的

// A StructTag is the tag string in a struct field.
//
// By convention, tag strings are a concatenation of
// optionally space-separated key:"value" pairs.
// Each key is a non-empty string consisting of non-control
// characters other than space (U+0020 ' '), quote (U+0022 '"'),
// and colon (U+003A ':').  Each value is quoted using U+0022 '"'
// characters and Go string literal syntax.
type StructTag string

StructTag 其实是就是string,和他相关的有Get和lookup两个方法,有兴趣自己研究下,可以根据这些方法获得标签值。

reflect.Value

go 反射粗略理解_第2张图片
value 通过Field 获得的依然是value类型,很好理解,value存储的是反射对象的值信息,它的field当然也是值信息。
接下来介绍几个重要的方法。

获取value的内存地址

// UnsafeAddr returns a pointer to v's data.
// It is for advanced clients that also import the "unsafe" package.
// It panics if v is not addressable.
func (v Value) UnsafeAddr() uintptr {
	// TODO: deprecate
	if v.typ == nil {
		panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
	}
	if v.flag&flagAddr == 0 {
		panic("reflect.Value.UnsafeAddr of unaddressable value")
	}
	return uintptr(v.ptr)
}

获取真实类型的泛型类型,注意直接调用value 获取的值只是拷贝,想要获取指针类型,需要调用Add().Interface()

// Interface returns v's current value as an interface{}.
// It is equivalent to:
//	var i interface{} = (v's underlying value)
// It panics if the Value was obtained by accessing
// unexported struct fields.
func (v Value) Interface() (i interface{}) {
	return valueInterface(v, true)
}

你可能感兴趣的:(编程日记)