【问题标题】:golang type assertion using reflect.Typeof()golang 类型断言使用 reflect.Typeof()
【发布时间】:2015-03-10 03:15:05
【问题描述】:

我尝试使用字符串值(名称)来识别结构。 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)

}

【问题讨论】:

  • 这在 Go 中是完全不可能的。类型断言仅断言编译时常量固定静态类型。你必须重新设计你的解决方案。

标签: types go typeof assertion


【解决方案1】:

如果需要开启外部接口的类型{}则不需要反射。

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()
  }
}

我还没有找到更清洁的方法,我很想知道它是否存在。

【讨论】:

  • 但这仅适用于确定的类型,不适用于自定义类型。如果我想为自定义结构类型做类型断言怎么办?
  • 在我的第二个示例中,您可以反映任何结构。 “int”只是一个在结构上循环遍历每个属性时发现属性的示例。
  • 我的意思是我们仍然必须迭代我们拥有的每种类型。无法使用 reflect.TypeOf 的类型,然后将其用于类型转换或通过字符串 x 进行类型转换。("customtype")
  • 不,你需要泛型:(
【解决方案2】:

从句法上讲,类型断言采用括号中的类型,而不是表达式。所以是语法错误。

您似乎正在尝试使用在运行时计算的值进行类型断言。那有意义吗?让我们想想什么是类型断言。

类型断言由两部分组成:

  1. 在编译时:它使结果表达式具有所需的编译时类型。表达式x.(T) 具有编译时类型T。这使您可以使用 T 类型执行的表达式,而您可能无法使用 x 类型执行的表达式。
  2. 在运行时:检查该值是否不是nil 并且实际上是给定的类型,如果不是,则会导致恐慌。

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

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

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

【讨论】:

    【解决方案3】:

    我认为您在这里寻找的是类型开关。 https://tour.golang.org/methods/16

    【讨论】:

      【解决方案4】:

      如果您可以处理噪音并实现所有类型都实现的额外方法,例如'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)
              }
      

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • ValueOf() 返回一个类型 reflect.Value 不是接口的实际底层类型...
        猜你喜欢
        • 2014-01-22
        • 2019-01-01
        • 2019-11-03
        • 1970-01-01
        • 2014-01-08
        • 1970-01-01
        • 1970-01-01
        • 2014-01-12
        • 2017-02-13
        相关资源
        最近更新 更多