如何在Go语言中找到对象的类型?

566

如何在Go中查找对象类型? 在Python中,我只需使用typeof获取对象的类型。同样,在Go中,是否有一种实现方式可以实现相同的功能?

这是我正在遍历的容器:

for e := dlist.Front(); e != nil; e = e.Next() {
    lines := e.Value
    fmt.Printf(reflect.TypeOf(lines))
}

在这种情况下,我无法获得对象“lines”的类型,该对象是一个字符串数组。


标准参考在我的程序中不起作用。我应该包含源代码,我的错。 - Rahul
39
fmt.Printf("%T\n", var) - meh
16个回答

677

Go语言的反射包提供了检查变量类型的方法。

以下代码片段将打印出字符串、整数和浮点数的反射类型。

package main

import (
    "fmt"
    "reflect"
)

func main() {

    tst := "string"
    tst2 := 10
    tst3 := 1.2

    fmt.Println(reflect.TypeOf(tst))
    fmt.Println(reflect.TypeOf(tst2))
    fmt.Println(reflect.TypeOf(tst3))

}

输出:

string
int
float64

查看演示: http://play.golang.org/p/XQMcUVsOja

更多文档请参考: http://golang.org/pkg/reflect/#Type


反射对我不起作用。我已更新问题。在这种情况下,我已包含了代码片段。 - Rahul

592
I found 3 ways to return a variable's type at runtime:

使用字符串格式化方法

func typeof(v interface{}) string {
    return fmt.Sprintf("%T", v)
}

使用 reflect package
func typeof(v interface{}) string {
    return reflect.TypeOf(v).String()
}

使用类型开关
func typeof(v interface{}) string {
    switch v.(type) {
    case int:
        return "int"
    case float64:
        return "float64"
    //... etc
    default:
        return "unknown"
    }
}

每种方法都有不同的最佳用例:

  • 字符串格式化 - 短小且占用空间少(不需要导入 reflect 包)

  • reflect 包 - 当需要更多关于类型的细节时,我们可以访问完整的反射功能

  • 类型开关 - 允许分组类型,例如将所有 int32、int64、uint32、uint64 类型识别为“int”


4
似乎你可以去掉变量t,所以t := v.(type)可以简化为v.(type),而且不再需要_ = t - Akavall
5
根据一个基本的基准测试,反射方法效率惊人地更高。https://gist.github.com/mrap/7f08c9549289b6aea2923c27888e7e3e - Mike Rapadas
2
使用反射打印类型的 fmt 包:case 'T': p.fmt.fmtS(reflect.TypeOf(arg).String()) - Fantasy_RQG
3
请注意,v.(type) 仅适用于 switch 语句。 - Riccardo Murri
2
@MikeRapadas 你错过了 switch 反射操作(例如 v.(type))。我修改了你的基准测试以使用它,结果发现使用 switch 更快。虽然该方法带有警告 - 感兴趣的类型必须明确定义才能有用。基准测试结果 - Rick B

60

使用reflect包:

reflect包实现了运行时反射,允许程序操作带有任意类型的对象。典型用法是以静态类型interface{}获取值,并通过调用TypeOf提取其动态类型信息,TypeOf会返回一个Type。

package main

import (
    "fmt"
    "reflect"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Println(reflect.TypeOf(b))
    fmt.Println(reflect.TypeOf(s))
    fmt.Println(reflect.TypeOf(n))
    fmt.Println(reflect.TypeOf(f))
    fmt.Println(reflect.TypeOf(a))
}

产生:

bool
string
int
float64
[]string

游乐场

使用ValueOf(i interface{}).Kind()的示例:

package main

import (
    "fmt"
    "reflect"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Println(reflect.ValueOf(b).Kind())
    fmt.Println(reflect.ValueOf(s).Kind())
    fmt.Println(reflect.ValueOf(n).Kind())
    fmt.Println(reflect.ValueOf(f).Kind())
    fmt.Println(reflect.ValueOf(a).Index(0).Kind()) // For slices and strings
}

生成:

bool
string
int
float64
string

游乐场


reflect只显示标准类型。我无法获取列表容器元素的类型。 - Rahul
我已经更新了我的答案,包括字符串切片。反射适用于任何类型。请阅读文档:http://golang.org/pkg/reflect/ 和 http://blog.golang.org/laws-of-reflection 应该足够了,虽然还有许多与Go中反射相关的SO问题也应该能帮助你。 - Intermernet
5
判断一个类型是否为字符串,应该使用 if reflect.TypeOf(err).Kind() == reflect.String - Alexander Mills

47

获取字符串表示:

来自http://golang.org/pkg/fmt/

%T 值类型的Go语法表示

package main
import "fmt"
func main(){
    types := []interface{} {"a",6,6.0,true}
    for _,v := range types{
        fmt.Printf("%T\n",v)
    }
}

输出:

string
int
float64
bool

17

我建议不要使用 reflect 包,而是使用 %T。

package main

import (
    "fmt"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Printf("%T\n", b)
    fmt.Printf("%T\n", s)
    fmt.Printf("%T\n", n)
    fmt.Printf("%T\n", f)
    fmt.Printf("%T\n", a)
 }

16

最佳方式是在Google中使用反射概念。
reflect.TypeOf 提供类型及其包名信息
reflect.TypeOf().Kind() 提供底层类型


11

简单来说,请使用fmt包中的fmt.Printf("%T", var1)或其它变体。


6
如果我们有这些变量:
var counter int = 5
var message string  = "Hello"
var factor float32 = 4.2
var enabled bool = false

1: fmt.Printf %T格式:使用该功能需要导入“fmt”包

fmt.Printf("%T \n",factor )   // factor type: float32

2: reflect.TypeOf函数:使用此功能,您应该导入“reflect”

fmt.Println(reflect.TypeOf(enabled)) // enabled type:  bool

3: reflect.ValueOf(X).Kind():要使用此功能,您应该导入“reflect”

fmt.Println(reflect.ValueOf(counter).Kind()) // counter type:  int

5
你可以使用"reflect"包的函数或使用在运行时检查任何变量/实例的类型:
package main

import (
   "fmt"
   "reflect"
)

func main() {
    value1 := "Have a Good Day"
    value2 := 50
    value3 := 50.78

    fmt.Println(reflect.TypeOf(value1 ))
    fmt.Println(reflect.TypeOf(value2))
    fmt.Println(reflect.TypeOf(value3))
    fmt.Printf("%T",value1)
    fmt.Printf("%T",value2)
    fmt.Printf("%T",value3)
}

5
获取结构体中字段的类型。
package main

import (
  "fmt"
  "reflect"
)

type testObject struct {
  Name   string
  Age    int
  Height float64
}

func main() {
   tstObj := testObject{Name: "yog prakash", Age: 24, Height: 5.6}
   val := reflect.ValueOf(&tstObj).Elem()
   typeOfTstObj := val.Type()
   for i := 0; i < val.NumField(); i++ {
       fieldType := val.Field(i)
       fmt.Printf("object field %d key=%s value=%v type=%s \n",
          i, typeOfTstObj.Field(i).Name, fieldType.Interface(),
          fieldType.Type())
   }
}

输出

object field 0 key=Name value=yog prakash type=string 
object field 1 key=Age value=24 type=int 
object field 2 key=Height value=5.6 type=float64

在IDE中查看 https://play.golang.org/p/bwIpYnBQiE


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