使用`reflect.TypeOf()`进行Golang类型断言。

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

golang type assertion using reflect.Typeof()

问题

我已经尝试使用字符串值(名称)来识别一个结构体。
reflect.TypeOf 返回 Type

但是类型断言需要一个 type

如何将 Type 转换为 type

或者有没有其他处理方法的建议?

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) 不是一个类型
	fmt.Printf("Hello, item2: %v\n", item2)

}
英文:

I've tried to identify a struct with string value(name).
reflect.TypeOf returns Type.

But type assertion needs a type.

How can I casting Type to type?

Or any suggestion to handle it?

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)

}

答案1

得分: 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()
  }
}

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

英文:

If you need to switch on the type of the outer interface{} you wont need reflection.

switch x.(type){
  case int: 
    dosomething()
}

...but if you need to switch on the type of the attributes in an interface then you can do this:

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

I haven't found a cleaner way, I'd love to know if it exists.

答案2

得分: 9

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

你似乎试图在运行时使用计算得到的值进行类型断言。这样做有意义吗?让我们思考一下类型断言的含义。

类型断言由两部分组成:

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

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

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

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

A type assertion, syntactically, takes a type in the parentheses, not an expression. So it is a syntax error.

You seem to be trying to do a type assertion with a value computed at runtime. Does that make sense? Let's think about what a type assertion is.

A type assertion consists of two things:

  1. At compile time: It causes the resulting expression to have the desired compile-time type. The expression x.(T) has compile-time type T. This allows you to do stuff the expression that you can do with type T, which you may not be able to do with the type of x.
  2. At runtime: It checks whether the value is not nil and is actually of the given type, and if not, it causes a panic.

The first part obviously doesn't make sense for a type computed at runtime. The compile-time type of the resulting expression cannot depend on something that is not known at compile-time.

The second one (runtime check) can be done with a type computed at runtime. Something like:

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

答案3

得分: 6

很多事情,但基本上是“它不是这样工作的”。类型断言中括号内的内容必须是一个类型(https://golang.org/ref/spec#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)

英文:

Lots of things, but basically "it doesn't work that way". The thing inside the parentheses in a type assertion needs to be a type, that is a type name or a type literal. reflect.TypeOf(i) isn't one of those, it's a method call expression. Therefore this is a syntax error. reflect.TypeOf doesn't "return a type" (which isn't really a thing you can do in Go), it returns a reflect.Type, which is an ordinary go struct that contains information about a type (i.e. sort of a meta-type).

But the more fundamental reason why it doesn't work is because it can't... Go needs to know what the type of a variable is when it's declared. Either its type is given explicitly in a var declaration, or it's inferred from the type of the initialization value in a var x = value declaration or x := value short assignment. It is not possible for the type to be unknown at compile time. Go doesn't let you write an expression that produces an undetermined type.

The very purpose of a type assertion is to take a value of an interface type (which is a kind of "box" that can hold values of multiple types, or for interface{}, any type at all) and retrieve a value of a specific concrete type. The value produced by the assertion will have the type named by the assertion, and no other. (In the case of a ,ok assignment, if the assertion fails, the variable will hold a zero value but still be of the correct type). If you could write an assertion to a type that was known only at runtime, the whole thing would fall apart, so you can't write it — it's an error.

In short, you can't use reflection to do that. You can use reflect to learn what the type of i is, you can learn that type's name, you can learn that its underlying Kind is Struct, you can enumerate the struct's fields and get the values out of them, etc... all of these are legitimate uses of reflection. But it can't give you back a variable of type MyStruct — the way to do that is i.(MyStruct).

答案4

得分: 3

我认为你在这里寻找的是类型切换。
https://tour.golang.org/methods/16

英文:

I think what you're looking for here is a type switch.
https://tour.golang.org/methods/16

答案5

得分: 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)
		}
英文:

If you can handle the noise and implement an extra method which all the types implement e.g. 'Type() string', you can do something like this:

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

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

答案6

得分: -3

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

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

英文:

I think you can use ValueOf to solve this

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

huangapple
  • 本文由 发表于 2015年1月12日 19:06:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/27900568.html
匿名

发表评论

匿名网友

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

确定