英文:
In go reflection package, is the call Value.Kind() a syntactic sugar to Value.Type().Kind()?
问题
reflect.Type
接口和reflect.Value
类型都实现了相同的Kind()
方法签名。假设我们有一个值对象v := reflect.ValueOf(x)
。
那么,v.Kind()
是否只是调用v.Type().Kind()
?
英文:
Both of the reflect.Type interface and reflect.Value type implement the same Kind()
method signature, suppose that we have some value object v := reflect.ValueOf(x)
Is v.Kind()
just call v.Type().Kind()
?
答案1
得分: 2
它们包含相同的值,但似乎不指向同一物体:
Type
通常由未导出的结构体 rtype
实现(通过 TypeOf
),而 Value
包含一个 *rtype
并扩展了 flag
,它本身是 Kind
的简化形式:
// flag 保存有关值的元数据。
// 最低位是标志位:
// - flagRO:通过未导出的字段获得,因此只读
// - flagIndir:val 持有指向数据的指针
// - flagAddr:v.CanAddr 为 true(意味着 flagIndir 为真)
// - flagMethod:v 是方法值。
// 接下来的五位给出了值的 Kind。
// 这重复了 typ.Kind(),但对于方法值除外。
// 剩下的 23+ 位给出了方法值的方法编号。
// 如果 flag.kind() != Func,则代码可以假设 flagMethod 未设置。
// 如果 typ.size > ptrSize,则代码可以假设 flagIndir 已设置。
当获取某个东西的 ValueOf
时:
// ValueOf 返回一个新的 Value,其初始化为接口 i 中存储的具体值。
// ValueOf(nil) 返回零值 Value。
func ValueOf(i interface{}) Value {
[...]
// 对于设置了 noAddr 位的接口值,其表示与空接口相同。
eface := *(*emptyInterface)(unsafe.Pointer(&i))
typ := eface.typ
/** Flag is built from the type, then kept separate (my comment) */
fl := flag(typ.Kind()) << flagKindShift
if typ.size > ptrSize {
fl |= flagIndir
}
return Value{typ, unsafe.Pointer(eface.word), fl}
}
因此,当你获取一个值的类型时(记住它扩展了它的 flag):
func (v Value) Kind() Kind {
return v.kind()
}
func (f flag) kind() Kind {
return Kind((f >> flagKindShift) & flagKindMask)
}
而获取一个类型的 kind 时(Type
是一个接口,通常由 *rtype
实现):
func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
所以尽管它们在大多数情况下似乎相等,v.Kind()
不等于 v.Type().Kind()
。
英文:
They contain the same value, but do not seem to refer to the same thing:
A Type
is usually implemented by unexported struct rtype
(via TypeOf
), while the Value
contains a *rtype
and extends flag
, which is itself a reduced form of the Kind
:
// flag holds metadata about the value.
// The lowest bits are flag bits:
// - flagRO: obtained via unexported field, so read-only
// - flagIndir: val holds a pointer to the data
// - flagAddr: v.CanAddr is true (implies flagIndir)
// - flagMethod: v is a method value.
// The next five bits give the Kind of the value.
// This repeats typ.Kind() except for method values.
// The remaining 23+ bits give a method number for method values.
// If flag.kind() != Func, code can assume that flagMethod is unset.
// If typ.size > ptrSize, code can assume that flagIndir is set.
When getting the ValueOf
something:
// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
func ValueOf(i interface{}) Value {
[...]
// For an interface value with the noAddr bit set,
// the representation is identical to an empty interface.
eface := *(*emptyInterface)(unsafe.Pointer(&i))
typ := eface.typ
/** Flag is built from the type, then kept separate (my comment) */
fl := flag(typ.Kind()) << flagKindShift
if typ.size > ptrSize {
fl |= flagIndir
}
return Value{typ, unsafe.Pointer(eface.word), fl}
}
And so when you get the kind of a Value (remember it extends its flag):
func (v Value) Kind() Kind {
return v.kind()
}
func (f flag) kind() Kind {
return Kind((f >> flagKindShift) & flagKindMask)
}
While getting the kind of a type: (Type
is an interface, usually implemented by *rtype
)
func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
So although they seem to be equal in most of the cases, v.Kind()
is not v.Type().Kind()
答案2
得分: 0
文件reflect/value.go中指出,reflect.Value
的实现中相关字段“重复了typ.Kind(),除了方法值”。因此,除非该值是一个方法,否则value.Kind()
和value.Type().Kind()
返回相同的数字。
英文:
The file reflect/value.go states that the relevant field in the implementation of reflect.Value
"repeats typ.Kind() except for method values". So, unless the value is a method, value.Kind()
and value.Type().Kind()
return the same number.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论