如何启用reflect.Type?

Ser*_*i G 5 reflection go

我设法做到了这一点,但看起来效率不高:

var t reflect.Type
switch t {
case reflect.TypeOf(([]uint8)(nil)):
    // handle []uint8 array type
}
Run Code Online (Sandbox Code Playgroud)

cap*_*aig 8

如果您只是想检测类型,则可能不需要反射。

switch t := myVar.(type){
  case []uint8:
    // t is []uint8
  case *Foo:
    // t is *Foo
  default:
    panic("unknown type")
}
Run Code Online (Sandbox Code Playgroud)

你真正想要完成什么?


Ste*_*erg 7

第一个问题,您确定要打开reflect.Type并且不使用类型开关吗?例:

switch x := y.(type) {
case []uint8:
  // x is now a []uint8
}
Run Code Online (Sandbox Code Playgroud)

假设这对你的情况不起作用,我的建议是制作那些包变量.例:

var uint8SliceType = reflect.TypeOf(([]uint8)(nil))

func Foo() {
    var t reflect.Type
    switch t {
    case uint8SliceType:
        // handle []uint8 array type
    }

}
Run Code Online (Sandbox Code Playgroud)


Dav*_*rdt 6

最初问题的答案如何开启reflect.Type?是:你可以\xe2\x80\x99t。但是,您可以使用 来做到这一点reflect.Value

\n
    \n
  • 给定一个变量,v interface{}您可以调用reflect.TypeOf(v)and reflect.ValueOf(v),分别返回reflect.Typeor reflect.Value、 \n
      \n
    • 如果 的类型v不是,interface{}那么这些函数调用会将其转换为interface{}.
    • \n
    \n
  • \n
  • reflect.Type包含有关该类型的各种运行时信息,但它不包含v任何可用于在类型切换中根据需要检索其自身类型的任何信息。
  • \n
  • 然而,reflect.Value通过其方法提供它Interface(),该方法返回底层值interface{}。您可以在类型开关或类型断言中使用它。
  • \n
\n
import "fmt"\nimport "reflect"\n\nvar v int\nvar rt reflect.Type = reflect.TypeOf(v)\nfmt.Println(rt.String(), " has awesome properties: Its alignment is",\n    rt.Align(), ", it has", rt.Size(), "bytes, is it even comparable?",\n    rt.Comparable())\n// \xe2\x80\xa6 but reflect.Type won\xe2\x80\x99t tell us what the real type is :(\n// Let\xe2\x80\x99s see if reflect.Value can help us.\nvar rv reflect.Value = reflect.ValueOf(v)\n// Here we go:\nvi := rv.Interface()\nswitch vi.(type) {\n// Mission accomplished.\n}\n
Run Code Online (Sandbox Code Playgroud)\n

也许它有助于澄清一些可能导致 Go 中动态类型混乱的点。至少我为此困惑了相当长的一段时间。

\n

reflectinterface{}

\n

Go 有两种运行时泛型系统:

\n
    \n
  • 语言:中interface{},对于类型开关/断言很有用,
  • \n
  • 在库中:reflect包,对于检查运行时泛型类型及其值很有用。
  • \n
\n

这两个系统是两个不同的世界,其中一个系统可以做到的事情,另一个系统则不可能。例如,给定 an interface{},在普通 Go(使用安全代码)中,如果该值是数组或切片,无论其元素类型如何,都不可能获取第 i 个元素的值。reflect为了做到这一点,人们需要使用。相反, withreflect是不可能进行类型切换或断言的:将其转换为interface{},然后就可以做到这一点。

\n

这些系统之间的接口点很少。在一个方向上,TypeOf()ValueOf()函数接受interface{}并返回一个reflect结构。反之亦然Value.Interface()

\n

需要 aValue而不是 aType来进行类型切换,这有点违反直觉。至少这与需要Type通过调用来构造值 a 的事实有些一致TypeOf()

\n

reflect.Kind

\n

两者reflect.Type都有reflect.Value一个Kind()方法。有些人建议使用这些方法返回的值(类型为 )reflect.Kind来模拟类型切换。

\n

虽然这在某些情况下可能很有用,但它并不能替代类型开关。例如,使用Kindone 无法区分int64time.Duration因为后者被定义

\n
type Duration int64\n
Run Code Online (Sandbox Code Playgroud)\n

Kind可以用来判断一个类型是否是任何类型的结构体、数组、切片等,无论它由什么类型组成。这是不可能用类型开关找出的。

\n

(旁注。我有同样的问题,发现这里没有答案有帮助,所以我自己去弄清楚。重复的反问 \xe2\x80\x9cwhy are you do this?\xe2\x80\x9d,后面是不相关的问题答案也对我没有帮助。我有充分的理由为什么我想这样做。)

\n