使用reflect.Typeof()进行golang类型断言

23

我尝试使用字符串值(名称)来识别结构体。

reflect.TypeOf返回Type

但类型断言需要一个type

如何将Type转换为type

或者有什么建议来处理它吗?

http://play.golang.org/p/3PJG3YxIyf

package main

import (
"fmt"
"reflect"
)
type Article struct {
    Id             int64       `json:"id"`
    Title          string      `json:"title",sql:"size:255"`
    Content        string      `json:"content"`
}


func IdentifyItemType(name string) interface{} {
    var item interface{}
    switch name {
    default:
        item = Article{}
    }
    return item
}

func main() {

    i := IdentifyItemType("name")
    item := i.(Article)
    fmt.Printf("Hello, item : %v\n", item)
    item2 := i.(reflect.TypeOf(i))  // reflect.TypeOf(i) is not a type
    fmt.Printf("Hello, item2 : %v\n", item2)

}

9
在Go语言中,这是完全不可能的。类型断言只能断言编译时常量固定静态类型。你需要重新设计你的解决方案。 - Volker
6个回答

10
如果您需要在外部接口{}的类型上切换,您将不需要反射。
switch x.(type){
  case int: 
    dosomething()
}

...但是如果你需要在接口中开启属性类型,则可以执行以下操作:

s := reflect.ValueOf(x)
for i:=0; i<s.NumValues; i++{
  switch s.Field(i).Interface().(type){
    case int: 
      dosomething()
  }
}

我还没有发现更简洁的方法,如果有的话我很想知道。


但这只适用于确定的类型,而不适用于自定义类型。如果我想对自定义结构类型进行类型断言呢? - TomSawyer
在我的第二个例子中,您可以反映任何结构。 “int”只是一个示例,在循环遍历每个属性时发现结构上的属性。 - MondayPaper
我的意思是我们仍然需要迭代我们拥有的每种类型。没有办法使用 reflect.TypeOf 的类型,然后将其用于类型转换或通过字符串 x 进行类型转换。("customtype") - TomSawyer
不好意思,你需要泛型来实现这个功能 :( - MondayPaper

9

类型断言在语法上需要在括号中写入一个类型,而不是表达式。因此这是一个语法错误。

您似乎试图使用在运行时计算的值进行类型断言。这有意义吗?让我们想一下类型断言的含义。

类型断言由两部分组成:

  1. 在编译时:它使得结果表达式具有所需的编译时类型。表达式 x.(T) 的编译时类型为 T。这允许您对具有类型 T 的表达式进行操作,而这些操作可能无法用 x 的类型执行。
  2. 在运行时:它检查该值是否不是 nil 并且实际上是给定类型,如果不是,则引发恐慌。

显然,第一部分对于在运行时计算的类型没有意义。结果表达式的编译时类型不能依赖于在编译时未知的内容。

第二部分(运行时检查)可以使用在运行时计算的类型来完成。例如:

if reflect.TypeOf(x) != someTypeComputedAtRuntime {
    panic(42)
}

6
许多事情,但基本上“它不是那样工作的”。类型断言括号内的内容需要是type,即类型名称或类型文字。 reflect.TypeOf(i) 不属于这些内容,它是一个方法调用表达式。因此,这是一种语法错误。 reflect.TypeOf 不会“返回类型”(在Go中实际上不是你可以做的事情),它返回一个reflect.Type,这是一个普通的go结构,包含关于类型的信息(即一种元类型)。

但它不能正常工作的更根本原因是因为它无法... Go需要在变量被声明时知道其类型。要么在var声明中明确给出其类型,要么从var x = value声明或x := value短赋值中初始化值的类型推断出其类型。在编译时,类型不可能未知。Go不允许您编写产生未确定类型的表达式。

类型断言的目的是从接口类型的值(这是一种可以容纳多种类型的值的“盒子”,或对于 interface{},任何类型)中检索特定具体类型的值。断言产生的值将具有断言命名的类型,而没有其他类型。(在 ,ok 赋值的情况下,如果断言失败,变量将保存 零值,但仍然是正确的类型)。如果您可以编写一个只在运行时才知道的类型的断言,整个程序就会崩溃,因此您不能编写它——这是一个错误。
简而言之,你无法使用反射来完成这个操作。你可以使用反射来了解i的类型,了解该类型的名称,了解其底层Kind是Struct,枚举结构体的字段并从中获取值等等……所有这些都是反射的合法用途。但它不能给你返回一个类型为MyStruct的变量——做到这一点的方法是i.(MyStruct)

3

2

如果您能够处理噪音并实现一个额外的方法,让所有类型都实现,例如 'Type() string',那么您可以像这样做:

        ve := &ValidationError{}
        nf := &NotFound{}

        switch err.Type() {
        case ve.Type() :
            SendBadRequest(w, err)
        case nf.Type() :
            http.NotFound(w, r)
        default:
            SendInternalError(w, err)
        }

-3

我认为你可以使用 ValueOf 来解决这个问题

item2 :=  reflect.ValueOf(i)
fmt.Printf("Hello, item2 : %v\n", item2)

3
ValueOf() 返回 reflect.Value 类型而不是接口的底层实际类型... - prl900

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接