在Go的反射包中,调用Value.Kind()是不是Value.Type().Kind()的语法糖?

huangapple go评论63阅读模式
英文:

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 &gt; 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(&amp;i))
    typ := eface.typ


    /** Flag is built from the type, then kept separate (my comment) */

    fl := flag(typ.Kind()) &lt;&lt; flagKindShift
    if typ.size &gt; 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 &gt;&gt; flagKindShift) &amp; 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 &amp; 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.

huangapple
  • 本文由 发表于 2013年12月14日 00:53:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/20571822.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定